You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2008/03/19 14:57:11 UTC
svn commit: r638834 [7/14] - in /jackrabbit/trunk:
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/principal/
jackr...
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/ACLImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/ACLImpl.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/ACLImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/ACLImpl.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.security.authorization.combined;
+
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.util.Text;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.Item;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <code>ACLImpl</code>...
+ */
+class ACLImpl {
+
+ private final Set acPaths;
+ private final Map principalToEntryArray;
+
+ private int privileges = -1;
+
+ ACLImpl(Map principalToEntryArray, Set acPaths) {
+ this.acPaths = acPaths;
+ this.principalToEntryArray = principalToEntryArray;
+ }
+
+ Set getAcPaths() {
+ return acPaths;
+ }
+
+ /**
+ * @param target Existing target item for which the permissions will be
+ * evaluated.
+ * @param protectsACL
+ * @return
+ * @throws RepositoryException
+ */
+ int getPermissions(Item target, boolean protectsACL) throws RepositoryException {
+ int allows = 0;
+ int denies = 0;
+ for (Iterator it = principalToEntryArray.keySet().iterator();
+ it.hasNext() && allows != Permission.ALL;) {
+ Principal princ = (Principal) it.next();
+ PolicyEntryImpl[] aces = (PolicyEntryImpl[]) principalToEntryArray.get(princ);
+ // loop over all entries and evaluate allows/denies for those
+ // matching the given jcrPath
+ for (int i = 0; i < aces.length; i++) {
+ PolicyEntryImpl entr = aces[i];
+ // TODO: check again if correct
+ if (entr.matches(target)) {
+ int privs = entr.getPrivilegeBits();
+ int permissions = Permission.calculatePermissions(privs, privs, protectsACL);
+ if (entr.isAllow()) {
+ allows |= Permission.diff(permissions, denies);
+ } else {
+ denies |= Permission.diff(permissions, allows);
+ }
+ }
+ }
+ }
+ return allows;
+ }
+
+ /**
+ *
+ * @param parent Existing parent of the target to be evaluated.
+ * @param targetName name of a non-existing child item to calculate the
+ * permissions for.
+ * @param protectsACL
+ * @return
+ * @throws RepositoryException
+ */
+ int getPermissions(Node parent, String targetName, boolean protectsACL) throws RepositoryException {
+ int allows = 0;
+ int denies = 0;
+ String jcrPath = parent.getPath() + "/" + targetName;
+ for (Iterator it = principalToEntryArray.keySet().iterator();
+ it.hasNext() && allows != Permission.ALL;) {
+ Principal princ = (Principal) it.next();
+ PolicyEntryImpl[] aces = (PolicyEntryImpl[]) principalToEntryArray.get(princ);
+ // loop over all entries and evaluate allows/denies for those
+ // matching the given jcrPath
+ // TODO: check if correct
+ for (int i = 0; i < aces.length; i++) {
+ PolicyEntryImpl entr = aces[i];
+ if (entr.matches(jcrPath)) {
+ int privs = entr.getPrivilegeBits();
+ int permissions = Permission.calculatePermissions(privs, privs, protectsACL);
+ if (entr.isAllow()) {
+ allows |= Permission.diff(permissions, denies);
+ } else {
+ denies |= Permission.diff(permissions, allows);
+ }
+ }
+ }
+ }
+ return allows;
+ }
+
+ int getPrivileges(String nodePath) throws RepositoryException {
+ if (privileges == -1) {
+ int allows = 0;
+ int denies = 0;
+ for (Iterator it = principalToEntryArray.keySet().iterator();
+ it.hasNext() && allows != Permission.ALL;) {
+ Principal princ = (Principal) it.next();
+ PolicyEntryImpl[] aces = (PolicyEntryImpl[]) principalToEntryArray.get(princ);
+ // loop over all entries and evaluate allows/denies for those
+ // matching the given jcrPath
+ for (int i = 0; i < aces.length; i++) {
+ PolicyEntryImpl entr = aces[i];
+ // TODO: check again which ACEs must be respected.
+ // TODO: maybe ancestor-defs only if glob = *?
+ String np = entr.getNodePath();
+ if (np.equals(nodePath) || Text.isDescendant(np, nodePath)) {
+ if (entr.isAllow()) {
+ allows |= PrivilegeRegistry.diff(entr.getPrivilegeBits(), denies);
+ } else {
+ denies |= PrivilegeRegistry.diff(entr.getPrivilegeBits(), allows);
+ }
+ }
+ }
+ }
+ privileges = allows;
+ }
+ return privileges;
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/ACLImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/ACLImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedEditor.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedEditor.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedEditor.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,359 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.security.authorization.combined;
+
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.core.security.authorization.AccessControlEditor;
+import org.apache.jackrabbit.core.security.authorization.PolicyTemplate;
+import org.apache.jackrabbit.core.security.authorization.AccessControlConstants;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.core.security.authorization.acl.ACLEditor;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlException;
+import org.apache.jackrabbit.core.security.jsr283.security.Privilege;
+import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
+import org.apache.jackrabbit.core.security.principal.ItemBasedPrincipal;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <code>CombinedEditor</code>...
+ */
+class CombinedEditor extends ACLEditor {
+
+ // TODO: must make sure, that store paths/globs do not contain remapped prefixes from the session
+
+ private static Logger log = LoggerFactory.getLogger(CombinedEditor.class);
+
+ private final SessionImpl session;
+ private final NamePathResolver systemResolver;
+ private final Path acRootPath;
+
+ CombinedEditor(SessionImpl session, NamePathResolver systemResolver,
+ Path acRootPath) throws RepositoryException {
+ super(session);
+ this.session = session;
+ this.systemResolver = systemResolver;
+ this.acRootPath = acRootPath;
+ }
+
+ PolicyTemplateImpl editPolicyTemplate(Principal principal) throws RepositoryException {
+ if (!session.getPrincipalManager().hasPrincipal(principal.getName())) {
+ throw new AccessControlException("Unknown principal.");
+ }
+ NodeId nid = getAcId(principal);
+ if (nid == null) {
+ nid = createAcNode(principal).getNodeId();
+ }
+
+ PolicyTemplate pt = getPolicyTemplate(nid);
+ if (pt instanceof PolicyTemplateImpl) {
+ return (PolicyTemplateImpl) pt;
+ } else {
+ // should never get here.
+ throw new AccessControlException();
+ }
+ }
+
+ PolicyTemplateImpl getPolicyTemplate(Principal principal) throws RepositoryException {
+ if (!session.getPrincipalManager().hasPrincipal(principal.getName())) {
+ throw new AccessControlException("Unknown principal.");
+ }
+
+ NodeId nid = getAcId(principal);
+ if (nid != null) {
+ PolicyTemplate pt = getPolicyTemplate(nid);
+ if (pt instanceof PolicyTemplateImpl) {
+ return (PolicyTemplateImpl) pt;
+ }
+ }
+
+ // no policy for the given principal
+ log.debug("No combined policy template for Principal " + principal.getName());
+ return null;
+ }
+
+ //------------------------------------------------< AccessControlEditor >---
+ /**
+ * @see AccessControlEditor#getPolicyTemplate(NodeId)
+ */
+ public PolicyTemplate getPolicyTemplate(NodeId id) throws AccessControlException, ItemNotFoundException, RepositoryException {
+ checkProtectsNode(id);
+
+ NodeImpl acNode = getAcNode(id);
+ if (acNode != null) {
+ if (isAccessControlled(acNode)) {
+ return buildTemplate(acNode);
+ } else {
+ log.debug("No local policy defined for Node " + id);
+ return null;
+ }
+ } else {
+ // nodeID not below rep:accesscontrol -> delegate to ACLEditor
+ return super.getPolicyTemplate(id);
+ }
+ }
+
+ /**
+ * @see AccessControlEditor#editPolicyTemplate(NodeId)
+ */
+ public PolicyTemplate editPolicyTemplate(NodeId id) throws AccessControlException, ItemNotFoundException, RepositoryException {
+ checkProtectsNode(id);
+
+ NodeImpl acNode = getAcNode(id);
+ if (acNode != null) {
+ return buildTemplate(acNode);
+ } else {
+ // nodeID not below rep:accesscontrol -> delegate to ACLEditor
+ return super.editPolicyTemplate(id);
+ }
+ }
+
+ /**
+ * @see AccessControlEditor#setPolicyTemplate(NodeId, PolicyTemplate)
+ */
+ public void setPolicyTemplate(NodeId id, PolicyTemplate template) throws AccessControlException, ItemNotFoundException, RepositoryException {
+ checkProtectsNode(id);
+
+ if (template instanceof PolicyTemplateImpl) {
+ PolicyTemplateImpl at = (PolicyTemplateImpl) template;
+ if (!id.equals(at.getNodeId())) {
+ throw new AccessControlException("Attempt to store PolicyTemplate to a wrong node.");
+ }
+ NodeImpl acNode = getAcNode(id);
+ if (acNode == null) {
+ throw new ItemNotFoundException("No such node " + id);
+ }
+
+ /*
+ in order to assert that the parent (ac-controlled node) gets
+ modified an existing ACL node is removed first and the recreated.
+ this also asserts that all ACEs are cleared without having to
+ access and removed the explicitely
+ */
+ NodeImpl aclNode;
+ if (acNode.hasNode(N_POLICY)) {
+ aclNode = acNode.getNode(N_POLICY);
+ removeSecurityItem(aclNode);
+ }
+ /* now (re) create it */
+ aclNode = addSecurityNode(acNode, N_POLICY, NT_REP_ACL);
+
+ /* add all entries defined on the template */
+ PolicyEntryImpl[] aces = (PolicyEntryImpl[]) template.getEntries();
+ for (int i = 0; i < aces.length; i++) {
+ PolicyEntryImpl ace = aces[i];
+
+ // create the ACE node
+ Name nodeName = getUniqueNodeName(aclNode, "entry");
+ Name ntName = (ace.isAllow()) ? NT_REP_GRANT_ACE : NT_REP_DENY_ACE;
+ NodeImpl aceNode = addSecurityNode(aclNode, nodeName, ntName);
+
+ ValueFactory vf = session.getValueFactory();
+ // write the rep:principalName property
+ setSecurityProperty(aceNode, P_PRINCIPAL_NAME, vf.createValue(ace.getPrincipal().getName()));
+ // ... and the rep:privileges property
+ Privilege[] privs = ace.getPrivileges();
+ Value[] vs = new Value[privs.length];
+ for (int j = 0; j < privs.length; j++) {
+ vs[i] = vf.createValue(privs[j].getName());
+ }
+ setSecurityProperty(aceNode, P_PRIVILEGES, vs);
+ setSecurityProperty(aceNode, P_NODE_PATH, vf.createValue(ace.getNodePath()));
+ setSecurityProperty(aceNode, P_GLOB, vf.createValue(ace.getGlob()));
+ }
+ } else {
+ // try super class
+ super.setPolicyTemplate(id, template);
+ }
+ }
+
+ /**
+ * @see AccessControlEditor#removePolicyTemplate(NodeId)
+ */
+ public PolicyTemplate removePolicyTemplate(NodeId id) throws AccessControlException, ItemNotFoundException, RepositoryException {
+ checkProtectsNode(id);
+
+ NodeImpl acNode = getAcNode(id);
+ if (acNode != null) {
+ if (isAccessControlled(acNode)) {
+ // build the template in order to have a return value
+ PolicyTemplate tmpl = buildTemplate(acNode);
+ removeSecurityItem(acNode.getNode(N_POLICY));
+ return tmpl;
+ } else {
+ log.debug("No policy present to remove at " + id);
+ return null;
+ }
+ } else {
+ // nodeID not below rep:accesscontrol -> delegate to ACLEditor
+ return super.removePolicyTemplate(id);
+ }
+ }
+
+ // TODO: check if get/add/remove entries are properly handled by super-class
+
+ //------------------------------------------------------------< private >---
+ /**
+ *
+ * @param nodeId
+ * @return
+ * @throws AccessControlException
+ * @throws RepositoryException
+ */
+ private NodeImpl getAcNode(NodeId nodeId) throws AccessControlException, RepositoryException {
+ NodeImpl n = session.getNodeById(nodeId);
+ Path p = session.getHierarchyManager().getPath(n.getNodeId());
+ if (p.isDescendantOf(acRootPath)) {
+ return n;
+ } else {
+ // node outside of rep:accesscontrol tree -> not handled by this editor.
+ return null;
+ }
+ }
+
+ private NodeId getAcId(Principal principal) throws RepositoryException {
+ Path acPath = session.getQPath(getPathToAcNode(principal));
+ return session.getHierarchyManager().resolveNodePath(acPath);
+ }
+
+ private NodeImpl createAcNode(Principal principal) throws RepositoryException {
+ String acPath = getPathToAcNode(principal);
+ String[] segms = Text.explode(acPath, '/', false);
+ NodeImpl node = (NodeImpl) session.getRootNode();
+ for (int i = 0; i < segms.length; i++) {
+ Name nName = session.getQName(segms[i]);
+ if (node.hasNode(nName)) {
+ node = node.getNode(nName);
+ if (!node.isNodeType(NT_REP_ACCESS_CONTROL)) {
+ // should never get here.
+ throw new RepositoryException("Internal error: Unexpected nodetype " + node.getPrimaryNodeType().getName() + " below /rep:accessControl");
+ }
+ } else {
+ node = addSecurityNode(node, nName, NT_REP_ACCESS_CONTROL);
+ }
+ }
+ return node;
+ }
+
+ /**
+ * Test if the Node identified by <code>id</code> is itself part of ACL
+ * defining content. It this case setting or modifying an AC-policy is
+ * obviously not possible.
+ *
+ * @param id
+ * @throws AccessControlException If the given id identifies a Node that
+ * represents a ACL or ACE item.
+ * @throws RepositoryException
+ */
+ private void checkProtectsNode(NodeId id) throws RepositoryException {
+ NodeImpl node = session.getNodeById(id);
+ if (node.isNodeType(NT_REP_ACL) || node.isNodeType(NT_REP_ACE)) {
+ throw new AccessControlException("Node " + id + " defines ACL or ACE.");
+ }
+ }
+
+ private String getPathToAcNode(Principal principal) throws RepositoryException {
+ StringBuffer princPath = new StringBuffer(session.getJCRPath(acRootPath));
+ if (principal instanceof ItemBasedPrincipal) {
+ princPath.append(((ItemBasedPrincipal) principal).getPath());
+ } else {
+ princPath.append("/");
+ princPath.append(Text.escapeIllegalJcrChars(principal.getName()));
+ }
+ return princPath.toString();
+ }
+
+ /**
+ *
+ * @param node
+ * @return
+ * @throws RepositoryException
+ */
+ private boolean isAccessControlled(NodeImpl node) throws RepositoryException {
+ return node.isNodeType(NT_REP_ACCESS_CONTROL) && node.hasNode(N_POLICY);
+ }
+
+ private PolicyTemplate buildTemplate(NodeImpl acNode) throws RepositoryException {
+ Principal principal;
+ String principalName = Text.unescapeIllegalJcrChars(acNode.getName());
+ PrincipalManager pMgr = ((SessionImpl) acNode.getSession()).getPrincipalManager();
+ if (pMgr.hasPrincipal(principalName)) {
+ principal = pMgr.getPrincipal(principalName);
+ } else {
+ log.warn("Principal with name " + principalName + " unknown to PrincipalManager.");
+ // TODO: rather throw?
+ principal = new PrincipalImpl(principalName);
+ }
+ return new PolicyTemplateImpl(getEntries(acNode, principal), principal, acNode.getNodeId());
+ }
+
+ private List getEntries(NodeImpl acNode, Principal principal) throws RepositoryException {
+ List entries = new ArrayList();
+ if (acNode.isNodeType(NT_REP_ACCESS_CONTROL) && acNode.hasNode(N_POLICY)) {
+ NodeImpl aclNode = acNode.getNode(N_POLICY);
+ // loop over all entries in the aclNode for the princ-Principal
+ // and compare if they apply to the Node with 'nodeId'
+ for (NodeIterator aceNodes = aclNode.getNodes(); aceNodes.hasNext();) {
+ NodeImpl aceNode = (NodeImpl) aceNodes.nextNode();
+ PolicyEntryImpl ace = createFromNode(aceNode, principal);
+ if (ace != null) {
+ entries.add(ace);
+ }
+ }
+ }
+ return entries;
+ }
+
+ private PolicyEntryImpl createFromNode(NodeImpl node, Principal principal) throws RepositoryException {
+ if (!node.isNodeType(AccessControlConstants.NT_REP_ACE)) {
+ log.warn("Unexpected nodetype. Was not rep:ACE.");
+ return null;
+ }
+
+ boolean allow = node.isNodeType(NT_REP_GRANT_ACE);
+
+ Value[] pValues = node.getProperty(P_PRIVILEGES).getValues();
+ String[] pNames = new String[pValues.length];
+ for (int i = 0; i < pValues.length; i++) {
+ pNames[i] = pValues[i].getString();
+ }
+ int privileges = PrivilegeRegistry.getBits(pNames);
+
+ String nodePath = node.getProperty(P_NODE_PATH).getString();
+ String glob = node.getProperty(P_GLOB).getString();
+
+ // TODO: mk sure principal and principal-name in node match
+
+ return new PolicyEntryImpl(principal, privileges, allow, nodePath, glob);
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedEditor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedEditor.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,352 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.security.authorization.combined;
+
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.security.SecurityConstants;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.core.security.authorization.AbstractAccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.AbstractCompiledPermissions;
+import org.apache.jackrabbit.core.security.authorization.AccessControlConstants;
+import org.apache.jackrabbit.core.security.authorization.AccessControlEditor;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.core.security.authorization.GlobPattern;
+import org.apache.jackrabbit.core.security.authorization.acl.ACLEditor;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlEntry;
+import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.util.Text;
+import org.apache.commons.collections.map.ListOrderedMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Node;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.ObservationManager;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.EventIterator;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * <code>CombinedProvider</code>...
+ */
+public class CombinedProvider extends AbstractAccessControlProvider implements AccessControlConstants {
+
+ private static Logger log = LoggerFactory.getLogger(CombinedProvider.class);
+
+ // TODO: add means to show effective-policy to a user.
+ // TODO: TOBEFIXED add means to create user-based ACLs (currently editor is not exposed in the API)
+ // TODO: TOBEFIXED proper evaluation of permissions respecting resource-based ACLs.
+ // TODO: TOBEFIXED assert proper evaluation order of group/non-group principal-ACLs
+
+ private SessionImpl session;
+ private ObservationManager obsMgr;
+
+ private CombinedEditor editor;
+ private NodeImpl acRoot;
+
+ protected CombinedProvider() {
+ super("Combined AC policy", "Policy evaluating user-based and resource-based ACLs.");
+ }
+ //----------------------------------------------< AccessControlProvider >---
+ /**
+ * @see AccessControlProvider#init(javax.jcr.Session, java.util.Map)
+ */
+ public void init(Session systemSession, Map options) throws RepositoryException {
+ if (initialized) {
+ throw new IllegalStateException("already initialized");
+ }
+ if (!(systemSession instanceof SessionImpl)) {
+ throw new RepositoryException("SessionImpl (system session) expected.");
+ }
+ session = (SessionImpl) systemSession;
+ obsMgr = session.getWorkspace().getObservationManager();
+
+ String rootPath = acRoot.getPath();
+ editor = new CombinedEditor(session, session.getNamePathResolver(),
+ session.getQPath(rootPath));
+ try {
+ log.info("Install initial ACL:...");
+
+ PrincipalManager pMgr = session.getPrincipalManager();
+ log.info("... Privilege.ALL for administrators.");
+ Principal administrators;
+ String pName = SecurityConstants.ADMINISTRATORS_NAME;
+ if (pMgr.hasPrincipal(pName)) {
+ administrators = pMgr.getPrincipal(pName);
+ } else {
+ log.warn("Administrators principal group is missing.");
+ administrators = new PrincipalImpl(pName);
+ }
+
+ String glob = GlobPattern.WILDCARD_ALL;
+ PolicyTemplateImpl pt = editor.editPolicyTemplate(administrators);
+ pt.setEntry(new PolicyEntryImpl(administrators, PrivilegeRegistry.ALL, true, rootPath, glob));
+ editor.setPolicyTemplate(pt.getNodeId(), pt);
+
+ Principal everyone = pMgr.getEveryone();
+ // TODO: to be improved. how to define where everyone has read-access
+ log.info("... Privilege.READ for everyone.");
+ pt = editor.editPolicyTemplate(everyone);
+ pt.setEntry(new PolicyEntryImpl(everyone, PrivilegeRegistry.READ, true, rootPath, glob));
+ editor.setPolicyTemplate(pt.getNodeId(), pt);
+
+ session.save();
+ log.info("... done.");
+
+ } catch (RepositoryException e) {
+ log.error("Failed to set-up minimal access control for root node of workspace " + session.getWorkspace().getName());
+ session.getRootNode().refresh(false);
+ throw e;
+ }
+
+
+ NodeImpl root = (NodeImpl) session.getRootNode();
+ if (root.hasNode(N_ACCESSCONTROL)) {
+ // TODO: make sure its a node with the correct nodetype
+ acRoot = root.getNode(N_ACCESSCONTROL);
+ if (!acRoot.isNodeType(NT_REP_ACCESS_CONTROL)) {
+ throw new RepositoryException("Error while initializing Access Control Provider: Found ac-root to be wrong node type " + acRoot.getPrimaryNodeType().getName());
+ }
+ } else {
+ acRoot = root.addNode(N_ACCESSCONTROL, NT_REP_ACCESS_CONTROL, null);
+ }
+ initialized = true;
+ }
+
+ /**
+ * @see AccessControlProvider#getAccessControlEntries(org.apache.jackrabbit.core.NodeId)
+ */
+ public AccessControlEntry[] getAccessControlEntries(NodeId nodeId) throws RepositoryException {
+ checkInitialized();
+ // TODO: TOBEFIXED
+ return new AccessControlEntry[0];
+ }
+
+ /**
+ * @see AccessControlProvider#getEditor(javax.jcr.Session)
+ */
+ public AccessControlEditor getEditor(Session editingSession) {
+ checkInitialized();
+ if (editingSession instanceof SessionImpl) {
+ try {
+ return new CombinedEditor((SessionImpl) editingSession,
+ session.getNamePathResolver(),
+ session.getQPath(acRoot.getPath()));
+ } catch (RepositoryException e) {
+ // should never get here
+ log.error("Internal error:", e.getMessage());
+ }
+ }
+
+ log.debug("Unable to createFromNode " + CombinedEditor.class.getName() + ".");
+ return null;
+ }
+
+ /**
+ * @see AccessControlProvider#compilePermissions(Set)
+ */
+ public CompiledPermissions compilePermissions(Set principals) throws ItemNotFoundException, RepositoryException {
+ checkInitialized();
+ if (isAdminOrSystem(principals)) {
+ return getAdminPermissions();
+ } else {
+ // TODO: include the resource-based ACLs!
+ return new CompiledPermissionImpl(principals);
+ }
+ }
+
+ //----------------------------------------< private | package protected >---
+ /**
+ * Test if the given path points to a Node (or an existing or non existing
+ * direct decendant of an existing Node) that stores AC-information
+ *
+ * @param path
+ * @return
+ * @throws RepositoryException
+ */
+ private boolean isAccessControlItem(Path path) throws ItemNotFoundException, RepositoryException {
+ NodeImpl node;
+ String absPath = session.getJCRPath(path);
+ if (session.nodeExists(absPath)) {
+ node = (NodeImpl) session.getNode(absPath);
+ } else {
+ // path points to existing prop or non-existing item (node or prop).
+ String parentPath = Text.getRelativeParent(absPath, 1);
+ if (session.nodeExists(parentPath)) {
+ node = (NodeImpl) session.getNode(parentPath);
+ } else {
+ throw new ItemNotFoundException("No item exists at " + absPath + " nor at its direct ancestor.");
+ }
+ }
+ return node.isNodeType(ACLEditor.NT_REP_ACL) || node.isNodeType(ACLEditor.NT_REP_ACE);
+ }
+
+ /**
+ *
+ * @param principals
+ * @return
+ * @throws RepositoryException
+ */
+ private ACLImpl getACL(Set principals) throws RepositoryException {
+ // acNodes must be ordered in the same order as the principals
+ // in order to obtain proper acl-evalution in case the given
+ // principal-set is ordered.
+ Map princToACEs = new ListOrderedMap();
+ Set acPaths = new HashSet();
+ // build acl-hierarchy assuming that principal-order determines the
+ // acl-inheritance.
+ for (Iterator it = principals.iterator(); it.hasNext();) {
+ Principal princ = (Principal) it.next();
+ PolicyTemplateImpl at = editor.getPolicyTemplate(princ);
+ if (at == null) {
+ log.debug("No matching ACL node found for principal " + princ.getName() + " -> principal ignored.");
+ } else {
+ // retrieve the ACEs from the node
+ PolicyEntryImpl[] aces = (PolicyEntryImpl[]) at.getEntries();
+ princToACEs.put(princ, aces);
+
+ Path p = session.getHierarchyManager().getPath(at.getNodeId());
+ acPaths.add(session.getJCRPath(p));
+ }
+ }
+ return new ACLImpl(princToACEs, acPaths);
+ }
+
+ //-----------------------------------------------------< CompiledPolicy >---
+ /**
+ *
+ */
+ private class CompiledPermissionImpl extends AbstractCompiledPermissions
+ implements EventListener {
+
+ private final Set principals;
+ private ACLImpl acl;
+
+ /**
+ * @param principals
+ * @throws RepositoryException
+ */
+ private CompiledPermissionImpl(Set principals) throws RepositoryException {
+
+ this.principals = principals;
+ acl = getACL(principals);
+
+ // TODO: describe
+ // TODO: rather on CombinedProvider? -> but must keep references to the CompiledPermission then....?
+ int events = Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED |
+ Event.PROPERTY_REMOVED | Event.NODE_ADDED | Event.NODE_REMOVED;
+ String[] ntNames = new String[] {
+ session.getJCRName(NT_REP_ACE)
+ };
+ obsMgr.addEventListener(this, events, acRoot.getPath(), true, null, ntNames, true);
+ }
+
+ //------------------------------------< AbstractCompiledPermissions >---
+ /**
+ * @see AbstractCompiledPermissions#buildResult(Path)
+ */
+ protected Result buildResult(Path absPath) throws RepositoryException {
+ if (!absPath.isAbsolute()) {
+ throw new RepositoryException("Absolute path expected.");
+ }
+
+ String jcrPath = session.getJCRPath(absPath);
+ boolean isAclItem = isAccessControlItem(absPath);
+
+ int permissions;
+ if (session.itemExists(jcrPath)) {
+ permissions = acl.getPermissions(session.getItem(jcrPath), isAclItem);
+ } else {
+ Node parent = session.getNode(Text.getRelativeParent(jcrPath, 1));
+ String name = session.getJCRName(absPath.getNameElement().getName());
+ permissions = acl.getPermissions(parent, name, isAclItem);
+ }
+ /* privileges can only be determined for existing nodes.
+ not for properties and neither for non-existing nodes. */
+ int privileges = (session.nodeExists(jcrPath)) ? acl.getPrivileges(jcrPath) : PrivilegeRegistry.NO_PRIVILEGE;
+ return new Result(permissions, privileges);
+ }
+
+ //--------------------------------------------< CompiledPermissions >---
+ /**
+ * @see CompiledPermissions#close()
+ */
+ public void close() {
+ try {
+ obsMgr.removeEventListener(this);
+ } catch (RepositoryException e) {
+ log.error("Internal error: ", e.getMessage());
+ }
+ super.close();
+ }
+
+ //--------------------------------------------------< EventListener >---
+ /**
+ * @see EventListener#onEvent(EventIterator)
+ */
+ public void onEvent(EventIterator events) {
+ Set acPaths = acl.getAcPaths();
+ try {
+ boolean reload = false;
+ while (events.hasNext() && !reload) {
+ Event ev = events.nextEvent();
+ String path = ev.getPath();
+ // only invalidate cache if any of the events affects the
+ // nodes defining permissions for the principals.
+ switch (ev.getType()) {
+ case Event.NODE_ADDED:
+ case Event.NODE_REMOVED:
+ reload = acPaths.contains(Text.getRelativeParent(path, 2));
+ break;
+ case Event.PROPERTY_ADDED:
+ case Event.PROPERTY_CHANGED:
+ case Event.PROPERTY_REMOVED:
+ reload = acPaths.contains(Text.getRelativeParent(path, 3));
+ break;
+ default:
+ // illegal event-type: should never occur. ignore
+ reload = false;
+ break;
+ }
+
+ }
+
+ // eventually reload the ACL and clear the cache
+ if (reload) {
+ // reload the acl
+ acl = getACL(principals);
+ clearCache();
+ }
+ } catch (RepositoryException e) {
+ // should never get here
+ log.warn("Internal error: ", e.getMessage());
+ }
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyEntryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyEntryImpl.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyEntryImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyEntryImpl.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.security.authorization.combined;
+
+import org.apache.jackrabbit.core.security.authorization.PolicyEntry;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
+import org.apache.jackrabbit.core.security.authorization.GlobPattern;
+import org.apache.jackrabbit.core.security.jsr283.security.Privilege;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlEntry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Item;
+import java.security.Principal;
+
+/**
+ * <code>PolicyEntryImpl</code>...
+ */
+class PolicyEntryImpl implements PolicyEntry {
+
+ private static Logger log = LoggerFactory.getLogger(PolicyEntryImpl.class);
+
+ /**
+ * Privileges defined for this entry.
+ */
+ private final int privileges;
+
+ /**
+ * If the actions contained are allowed or denied
+ */
+ private final boolean allow;
+
+ /**
+ * The Principal of this entry
+ */
+ private final Principal principal;
+
+ private final String nodePath;
+ private final String glob;
+
+ /**
+ * Globbing pattern
+ */
+ private final GlobPattern pattern;
+
+ /**
+ * Hash code being calculated on demand.
+ */
+ private int hashCode = -1;
+
+ /**
+ * Constructs an new entry.
+ *
+ * @param principal
+ * @param privileges
+ * @param allow
+ */
+ PolicyEntryImpl(Principal principal, int privileges, boolean allow,
+ String nodePath, String glob) {
+ if (principal == null || nodePath == null) {
+ throw new IllegalArgumentException("Neither principal nor nodePath must be null.");
+ }
+ this.principal = principal;
+ this.privileges = privileges;
+ this.allow = allow;
+ this.nodePath = nodePath;
+ this.glob = (glob == null) ? GlobPattern.WILDCARD_ALL : glob;
+
+ pattern = GlobPattern.create(nodePath + "/" +glob);
+ }
+
+ int getPrivilegeBits() {
+ return privileges;
+ }
+
+ String getNodePath() {
+ return nodePath;
+ }
+
+ String getGlob() {
+ return glob;
+ }
+
+ boolean matches(String jcrPath) throws RepositoryException {
+ return pattern.matches(jcrPath);
+ }
+
+ boolean matches(Item item) throws RepositoryException {
+ return pattern.matches(item);
+ }
+
+ //-------------------------------------------------< AccessControlEntry >---
+ /**
+ * @see AccessControlEntry#getPrincipal()
+ */
+ public Principal getPrincipal() {
+ return principal;
+ }
+
+ /**
+ * @see AccessControlEntry#getPrivileges()
+ */
+ public Privilege[] getPrivileges() {
+ return PrivilegeRegistry.getPrivileges(privileges);
+ }
+
+ //--------------------------------------------------------< PolicyEntry >---
+ /**
+ * @return true if all actions contained in this Entry are allowed
+ * @see PolicyEntry#isAllow()
+ */
+ public boolean isAllow() {
+ return allow;
+ }
+
+ //-------------------------------------------------------------< Object >---
+ /**
+ * @see Object#hashCode()
+ */
+ public int hashCode() {
+ if (hashCode == -1) {
+ int h = 17;
+ h = 37 * h + principal.getName().hashCode();
+ h = 37 * h + privileges;
+ h = 37 * h + Boolean.valueOf(allow).hashCode();
+ h = 37 * h + nodePath.hashCode();
+ h = 37 * h + glob.hashCode();
+ hashCode = h;
+ }
+ return hashCode;
+ }
+
+ /**
+ * Returns true if the principal, the allow-flag, all privileges and
+ * the nodepath and the glob string are equal or the same, respectively.
+ *
+ * @param obj
+ * @return
+ * @see Object#equals(Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof PolicyEntryImpl) {
+ PolicyEntryImpl tmpl = (PolicyEntryImpl) obj;
+ // TODO: check again if comparing principal-name is sufficient
+ return principal.getName().equals(tmpl.principal.getName()) &&
+ allow == tmpl.allow &&
+ privileges == tmpl.privileges &&
+ glob.equals(tmpl.glob);
+ }
+ return false;
+ }
+
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyEntryImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyEntryImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyTemplateImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyTemplateImpl.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyTemplateImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyTemplateImpl.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.security.authorization.combined;
+
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.security.authorization.PolicyEntry;
+import org.apache.jackrabbit.core.security.authorization.PolicyTemplate;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.RepositoryException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
+
+/**
+ * <code>PolicyTemplateImpl</code>...
+ */
+class PolicyTemplateImpl implements PolicyTemplate {
+
+ private static Logger log = LoggerFactory.getLogger(PolicyTemplateImpl.class);
+
+ private final Principal principal;
+ private final NodeId acNodeId;
+ private final List entries = new ArrayList();
+
+
+ PolicyTemplateImpl(List aceTemplates, Principal principal, NodeId acNodeId) {
+ this.principal = principal;
+ this.entries.addAll(aceTemplates);
+ this.acNodeId = acNodeId;
+ }
+
+ NodeId getNodeId() {
+ return acNodeId;
+ }
+
+ Principal getPrincipal() {
+ return principal;
+ }
+
+ //-----------------------------------------------------< PolicyTemplate >---
+
+ public boolean isEmpty() {
+ return entries.isEmpty();
+ }
+
+ public int size() {
+ return entries.size();
+ }
+
+ public PolicyEntry[] getEntries() {
+ return (PolicyEntry[]) entries.toArray(new PolicyEntry[entries.size()]);
+ }
+
+ public boolean setEntry(PolicyEntry entry) throws AccessControlException, RepositoryException {
+ if (entry instanceof PolicyEntryImpl &&
+ principal.equals(entry.getPrincipal())) {
+ return internalAddEntry((PolicyEntryImpl) entry);
+ } else {
+ throw new AccessControlException("Invalid entry.");
+ }
+ }
+
+ public boolean removeEntry(PolicyEntry entry) throws AccessControlException, RepositoryException {
+ return entries.remove(entry);
+ }
+
+ //------------------------------------------------< AccessControlPolicy >---
+ /**
+ * @see org.apache.jackrabbit.core.security.jsr283.security.AccessControlPolicy#getName()
+ */
+ public String getName() throws RepositoryException {
+ return getClass().getName();
+ }
+
+ /**
+ * @see org.apache.jackrabbit.core.security.jsr283.security.AccessControlPolicy#getName()
+ */
+ public String getDescription() throws RepositoryException {
+ return "Template for the user-based ACL: each ACL defining the access permissions for a single principal.";
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ *
+ * @param entry
+ * @return
+ */
+ private synchronized boolean internalAddEntry(PolicyEntryImpl entry) {
+ if (entries.contains(entry)) {
+ log.debug("Entry is already contained in policy -> no modification.");
+ return false;
+ }
+
+ PolicyEntryImpl existing = null;
+ for (Iterator it = entries.iterator(); it.hasNext() && existing == null;) {
+ PolicyEntryImpl ex = (PolicyEntryImpl) it.next();
+ if (ex.getNodePath().equals(entry.getNodePath()) &&
+ ex.getGlob().equals(entry.getGlob()) &&
+ ex.isAllow() == entry.isAllow()) {
+ log.debug("Replacing existing policy entry: NodePath = " +
+ entry.getNodePath() +"; Glob = " +
+ entry.getGlob() + "; Changing privileges from " +
+ ex.getPrivilegeBits() + " to " + entry.getPrivilegeBits());
+ existing = ex;
+ }
+ }
+
+ if (existing != null) {
+ int index = entries.indexOf(existing);
+ return entries.set(index, entry) != null;
+ } else {
+ return entries.add(entry);
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyTemplateImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/PolicyTemplateImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlEntry.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlEntry.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlEntry.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlEntry.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,23 @@
+package org.apache.jackrabbit.core.security.jsr283.security;
+
+import java.security.Principal;
+
+/**
+ * An <code>AccessControlEntry</code> represents the association of one or more
+ * <code>Privilege</code> objects with a specific <code>Principal</code>.
+ *
+ * @since JCR 2.0
+ */
+public interface AccessControlEntry {
+ /**
+ * Returns the principal associated with this access control entry.
+ * @return a <code>Principal</code>.
+ */
+ public Principal getPrincipal();
+
+ /**
+ * Returns the privileges associated with this access control entry.
+ * @return an array of <code>Privilege</code>s.
+ */
+ public Privilege[] getPrivileges();
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlEntry.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlEntry.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlException.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlException.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlException.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlException.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,52 @@
+package org.apache.jackrabbit.core.security.jsr283.security;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Exception thrown by access control related methods of
+ * <code>AccessControlManager</code>.
+ *
+ * @since JCR 2.0
+ */
+public class AccessControlException extends RepositoryException {
+
+ /**
+ * Constructs a new instance of this class with <code>null</code> as its
+ * detail message.
+ */
+ public AccessControlException() {
+ super();
+ }
+
+ /**
+ * Constructs a new instance of this class with the specified detail
+ * message.
+ *
+ * @param message the detail message. The detail message is saved for
+ * later retrieval by the {@link #getMessage()} method.
+ */
+ public AccessControlException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new instance of this class with the specified detail
+ * message and root cause.
+ *
+ * @param message the detail message. The detail message is saved for
+ * later retrieval by the {@link #getMessage()} method.
+ * @param rootCause root failure cause
+ */
+ public AccessControlException(String message, Throwable rootCause) {
+ super(message, rootCause);
+ }
+
+ /**
+ * Constructs a new instance of this class with the specified root cause.
+ *
+ * @param rootCause root failure cause
+ */
+ public AccessControlException(Throwable rootCause) {
+ super(rootCause);
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlException.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlException.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlManager.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlManager.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlManager.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,330 @@
+package org.apache.jackrabbit.core.security.jsr283.security;
+
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import java.security.Principal;
+
+/**
+ * The <code>AccessControlManager</code> object is accessed via
+ * {@link javax.jcr.Session#getAccessControlManager()}. It provides methods for:
+ * <ul>
+ * <li>Access control discovery</li>
+ * <li>Assigning access control policies</li>
+ * <li>Assigning access control entries</li>
+ * </ul>
+ *
+ * @since JCR 2.0
+ */
+public interface AccessControlManager {
+
+ /**
+ * Returns the privileges supported for absolute path <code>absPath</code>,
+ * which must be an existing node.
+ * <p/>
+ * This method does not return the privileges held by the session. Instead,
+ * it returns the privileges that the repository supports.
+ *
+ * @param absPath an absolute path.
+ * @return an array of <code>Privilege</code>s.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to
+ * retrieve the node.
+ * @throws RepositoryException if another error occurs.
+ */
+ public Privilege[] getSupportedPrivileges(String absPath)
+ throws PathNotFoundException, RepositoryException;
+
+ /**
+ * Returns whether the session has the specified privileges for absolute
+ * path <code>absPath</code>, which must be an existing node.
+ * <p/>
+ * Testing an aggregate privilege is equivalent to testing each nonaggregate
+ * privilege among the set returned by calling
+ * <code>Privilege.getAggregatePrivileges()</code> for that privilege.
+ *
+ * @param absPath an absolute path.
+ * @param privileges an array of <code>Privilege</code>s.
+ * @return <code>true</code> if the session has the specified privileges;
+ * <code>false</code> otherwise.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to
+ * retrieve the node.
+ * @throws RepositoryException if another error occurs.
+ */
+ public boolean hasPrivileges(String absPath, Privilege[] privileges)
+ throws PathNotFoundException, RepositoryException;
+
+ /**
+ * Returns the privileges the session has for absolute path absPath, which
+ * must be an existing node.
+ * <p/>
+ * The returned privileges are those for which {@link #hasPrivileges} would
+ * return <code>true</code>.
+ *
+ * @param absPath an absolute path.
+ * @return an array of <code>Privilege</code>s.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to
+ * retrieve the node.
+ * @throws RepositoryException if another error occurs.
+ */
+ public Privilege[] getPrivileges(String absPath)
+ throws PathNotFoundException, RepositoryException;
+
+ /**
+ * Returns the <code>AccessControlPolicy</code> that has been set to
+ * the node at <code>absPath</code> or <code>null</code> if no
+ * policy has been set. This method reflects the binding state including
+ * transient policy modifications.
+ * <p/>
+ * Use {@link #getEffectivePolicy(String)} in order to determine the
+ * policy that effectively applies at <code>absPath</code>.
+ *
+ * @param absPath an absolute path.
+ * @return an <code>AccessControlPolicy</code> object or <code>null</code>.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to
+ * retrieve the node.
+ * @throws AccessDeniedException if the session lacks
+ * <code>GET_ACCESS_CONTROL</code> privilege
+ * for the <code>absPath</code> node.
+ * @throws RepositoryException if another error occurs.
+ */
+ public AccessControlPolicy getPolicy(String absPath)
+ throws PathNotFoundException, AccessDeniedException, RepositoryException;
+
+ /**
+ * Returns the <code>AccessControlPolicy</code> that currently is in effect
+ * at the node at <code>absPath</code>. This may be an
+ * <code>AccessControlPolicy</code> set through this API or some
+ * implementation specific (default) policy.
+ * </p>
+ *
+ * @param absPath an absolute path.
+ * @return an <code>AccessControlPolicy</code> object.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to
+ * retrieve the node.
+ * @throws AccessDeniedException if the session lacks
+ * <code>READ_ACCESS_CONTROL</code> privilege
+ * for the <code>absPath</code> node.
+ * @throws RepositoryException if another error occurs.
+ */
+ public AccessControlPolicy getEffectivePolicy(String absPath)
+ throws PathNotFoundException, AccessDeniedException, RepositoryException;
+
+ /**
+ * Returns the access control policies that are capable of being applied to
+ * the node at <code>absPath</code>.
+ *
+ * @param absPath an absolute path.
+ * @return an <code>AccessControlPolicyIterator</code> over the applicable
+ * access control policies or an empty iterator if no policies are
+ * applicable.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to
+ * retrieve the node.
+ * @throws AccessDeniedException if the session lacks
+ * <code>READ_ACCESS_CONTROL</code> privilege
+ * for the <code>absPath</code> node.
+ * @throws RepositoryException if another error occurs.
+ */
+ public AccessControlPolicyIterator getApplicablePolicies(String absPath)
+ throws PathNotFoundException, AccessDeniedException, RepositoryException;
+
+ /**
+ * Binds the <code>policy</code> to the node at <code>absPath</code>.
+ * <p/>
+ * Only one policy may be bound at a time. If more than one policy per node
+ * is required, the implementation should provide an appropriate aggregate
+ * policy among those returned by <code>getApplicablePolicies(absPath)</code>.
+ * The access control policy does not take effect until a <code>save</code>
+ * is performed.
+ * <p/>
+ * If the node has access control entries that were bound to it through the
+ * JCR API prior to the <code>setPolicy</code> call, then these entries may
+ * be deleted. Any implementation-specific (non-JCR) access control
+ * settings may be changed in response to a successful call to
+ * <code>setPolicy</code>.
+ *
+ * @param absPath an absolute path.
+ * @param policy the <code>AccessControlPolicy</code> to be applied.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to
+ * retrieve the node.
+ * @throws AccessControlException if the policy is not applicable.
+ * @throws AccessDeniedException if the session lacks
+ * <code>MODIFY_ACCESS_CONTROL</code>
+ * privilege for the <code>absPath</code> node.
+ * @throws RepositoryException if another error occurs.
+ */
+ public void setPolicy(String absPath, AccessControlPolicy policy)
+ throws PathNotFoundException, AccessControlException,
+ AccessDeniedException, RepositoryException;
+
+ /**
+ * Removes the <code>AccessControlPolicy</code> from the node at absPath and
+ * returns it.
+ * <p/>
+ *
+ * An <code>AccessControlPolicy</code> can only be removed if it was
+ * bound to the specified node through this API before. The effect of the
+ * removal only takes place upon <code>Session.save()</code>. Whichever
+ * defaults the implementation applies now take effect.
+ * Note, that an implementation default or any other effective
+ * <code>AccessControlPolicy</code> that has not been applied to the node
+ * before may never be removed using this method.
+ *
+ * @param absPath an absolute path.
+ * @return the removed <code>AccessControlPolicy</code>.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to
+ * retrieve the node.
+ * @throws AccessControlException if no policy exists.
+ * @throws AccessDeniedException if the session lacks
+ * <code>MODIFY_ACCESS_CONTROL</code>
+ * privilege for the <code>absPath</code> node.
+ * @throws RepositoryException if another error occurs.
+ */
+ public AccessControlPolicy removePolicy(String absPath)
+ throws PathNotFoundException, AccessControlException,
+ AccessDeniedException, RepositoryException;
+
+ /**
+ * Returns all access control entries assigned to the node at <code>absPath</code>
+ * including transient modifications made to the entries at <code>absPath</code>.
+ * <p/>
+ * This method is only guaranteed to return an <code>AccessControlEntry</code>
+ * if that <code>AccessControlEntry</code> has been assigned <i>through this API</i>.
+ *
+ * @param absPath an absolute path
+ * @return all access control entries assigned at to specified node.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to
+ * retrieve the node.
+ * @throws AccessDeniedException if the session lacks
+ * <code>READ_ACCESS_CONTROL</code> privilege
+ * for the <code>absPath</code> node.
+ * @throws UnsupportedRepositoryOperationException if access control
+ * is not supported.
+ * @throws RepositoryException if another error occurs.
+ */
+ public AccessControlEntry[] getAccessControlEntries(String absPath)
+ throws PathNotFoundException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
+
+ /**
+ * Returns the access control entries that are effective at the node at
+ * <code>absPath</code>.
+ * <p/>
+ * This method is intended for information purpose only and should allow
+ * the user to determine which entries are currently used for access control
+ * evaluation.
+ * </p>
+ * If an implementation is not able to determine the effective entries
+ * present at the given node it returns <code>null</code> in order to indicate
+ * that entries exists but the implementation cannot find them. If there
+ * are no entries present at the given node an empty array will be returned.
+ *
+ * @param absPath an absolute path
+ * @return the access control entries that are currently effective at the
+ * node at <code>absPath</code> or <code>null</code> if the
+ * implementation is not able to determine the effective entries.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to retrieve the node.
+ * @throws AccessDeniedException if the session lacks
+ * <code>READ_ACCESS_CONTROL</code> privilege for the
+ * <code>absPath</code> node.
+ * @throws UnsupportedRepositoryOperationException if access control
+ * is not supported.
+ * @throws RepositoryException if another error occurs.
+ */
+ public AccessControlEntry[] getEffectiveAccessControlEntries(String absPath)
+ throws PathNotFoundException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException;
+
+
+ /**
+ * Adds the access control entry consisting of the specified
+ * <code>principal</code> and the specified <code>privileges</code> to the
+ * node at <code>absPath</code>.
+ * <p/>
+ * This method returns the <code>AccessControlEntry</code> object constructed from the
+ * specified <code>principal</code> and contains at least the given <code>privileges</code>.
+ * An implementation may return a resulting ACE that combines the given <code>privileges</code>
+ * with those added by a previous call to <code>addAccessControlEntry</code> for the same
+ * <code>Principal</code>. However, a call to <code>addAccessControlEntry</code> for a given
+ * <code>Principal</code> can never remove a <code>Privilege</code> added by a previous call
+ * to <code>addAccessControlEntry</code>.
+ * <p/>
+ * The access control entry does not take effect until a <code>save</code>
+ * is performed.
+ * <p/>
+ * This method is guaranteed to affect only the privileges of the specified
+ * <code>principal</code>.
+ * <p/>
+ * This method <i>may</i> affect the privileges granted to that principal with
+ * respect to nodes other than that specified. However, if it does, it is
+ * guaranteed to only affect the privileges of those other nodes in the
+ * same way as it affects the privileges of the specified node.
+ *
+ * @param absPath an absolute path.
+ * @param principal a <code>Principal</code>.
+ * @param privileges an array of <code>Privilege</code>s.
+ * @return the <code>AccessControlEntry</code> object constructed from the
+ * specified <code>principal</code> and <code>privileges</code>.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to retrieve the node.
+ * @throws AccessControlException if the specified principal does not exist,
+ * if any of the specified privileges is not supported at
+ * <code>absPath</code> or if some other access control related
+ * exception occurs.
+ * @throws AccessDeniedException if the session lacks
+ * <code>MODIFY_ACCESS_CONTROL</code> privilege for the
+ * <code>absPath</code> node.
+ * @throws UnsupportedRepositoryOperationException if access control
+ * is not supported.
+ * @throws RepositoryException if another error occurs.
+ */
+ public AccessControlEntry addAccessControlEntry(String absPath,
+ Principal principal,
+ Privilege[] privileges)
+ throws PathNotFoundException, AccessControlException,
+ AccessDeniedException, UnsupportedRepositoryOperationException,
+ RepositoryException;
+
+ /**
+ * Removes the specified <code>AccessControlEntry</code> from the node at
+ * <code>absPath</code>.
+ * <p/>
+ * This method is guaranteed to affect only the privileges of the principal
+ * defined within the passed <code>AccessControlEntry</code>.
+ * <p/>
+ * This method <i>may</i> affect the privileges granted to that principal
+ * with respect to nodes other than that specified. However, if it does,
+ * it is guaranteed to only affect the privileges of those other nodes in
+ * the same way as it affects the privileges of the specified node.
+ * <p/>
+ * Only exactly those entries obtained through
+ * <code>getAccessControlEntries<code> can be removed. The effect of the
+ * removal only takes effect upon <code>Session.save()</code>.
+ *
+ * @param absPath an absolute path.
+ * @param ace the access control entry to be removed.
+ * @throws PathNotFoundException if no node at <code>absPath</code> exists
+ * or the session does not have privilege to retrieve the node.
+ * @throws AccessControlException
+ * if the specified entry is not
+ * present on the specified node.
+ * @throws AccessDeniedException if the session lacks
+ * <code>MODIFY_ACCESS_CONTROL</code> privilege for the
+ * <code>absPath</code> node.
+ * @throws UnsupportedRepositoryOperationException if access control
+ * is not supported.
+ * @throws RepositoryException if another error occurs.
+ */
+ public void removeAccessControlEntry(String absPath, AccessControlEntry ace)
+ throws PathNotFoundException, AccessControlException,
+ AccessDeniedException, UnsupportedRepositoryOperationException,
+ RepositoryException;
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicy.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicy.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicy.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicy.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,34 @@
+package org.apache.jackrabbit.core.security.jsr283.security;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * An <code>AccessControlPolicy</code> is an object with a name and an optional
+ * description. Examples of possible <code>AccessControlPolicy</code>
+ * implementations include access control lists or role-responsibility
+ * assignments.
+ *
+ * @since JCR 2.0
+ */
+public interface AccessControlPolicy {
+ /**
+ * Returns the name of the access control policy, which should be unique
+ * among the choices applicable to any particular node.
+ * It is presented to provide an easily identifiable choice for
+ * users choosing a policy to assign to a node.
+ *
+ * @return the name of the access control policy.
+ * @throws RepositoryException if an error occurs.
+ */
+ public String getName() throws RepositoryException;
+
+ /**
+ * Returns a human readable description of the access control policy which
+ * should be sufficient for allowing end users to chose between different
+ * policies to apply to a node.
+ *
+ * @return a human readable description of the access control policy.
+ * @throws RepositoryException if an error occurs.
+ */
+ public String getDescription() throws RepositoryException;
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicy.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicy.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicyIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicyIterator.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicyIterator.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicyIterator.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,23 @@
+package org.apache.jackrabbit.core.security.jsr283.security;
+
+import javax.jcr.RangeIterator;
+
+/**
+ * Allows easy iteration through a list of <code>AccessControlPolicy</code>s
+ * with <code>nextAccessControlPolicy</code> as well as a <code>skip</code>
+ * method inherited from <code>RangeIterator</code>.
+ *
+ * @since JCR 2.0
+ */
+public interface AccessControlPolicyIterator extends RangeIterator {
+
+ /**
+ * Returns the next <code>AccessControlPolicy</code> in the iteration.
+ *
+ * @return the next <code>AccessControlPolicy</code> in the iteration.
+ * @throws java.util.NoSuchElementException if iteration has no more
+ * <code>AccessControlPolicy</code>s.
+ */
+ public AccessControlPolicy nextAccessControlPolicy();
+
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicyIterator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/AccessControlPolicyIterator.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/Privilege.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/Privilege.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/Privilege.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/Privilege.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,131 @@
+package org.apache.jackrabbit.core.security.jsr283.security;
+
+/**
+ * A privilege represents the capability of performing a particular set
+ * of operations on items in the JCR repository. Each privilege is identified
+ * by a NAME that is unique across the set of privileges supported by a
+ * repository. JCR defines a set of standard privileges in the <code>jcr</code>
+ * namespace. Implementations may add additional privileges in namespaces other
+ * than <code>jcr</code>.
+ * <p/>
+ * A privilege may be an aggregate privilege. Aggregate privileges are sets of
+ * other privileges. Granting, denying, or testing an aggregate privilege is
+ * equivalent to individually granting, denying, or testing each privilege it
+ * contains. The privileges contained by an aggregate privilege may themselves
+ * be aggregate privileges if the resulting privilege graph is acyclic.
+ * <p/>
+ * A privilege may be an abstract privilege. Abstract privileges cannot
+ * themselves be granted or denied, but can be composed into aggregate privileges
+ * which are granted or denied.
+ * <p/>
+ * A privilege can be both aggregate and abstract.
+ *
+ * @since JCR 2.0
+ */
+public interface Privilege {
+
+ /**
+ * A constant representing <code>READ</code>, the privilege to retrieve
+ * a node and get its properties and their values.
+ */
+ public static final String READ = "javax.jcr.security.Privilege.READ";
+
+ /**
+ * A constant representing <code>MODIFY_PROPERTIES</code>, the privilege
+ * to create, modify and remove the properties of a node.
+ */
+ public static final String MODIFY_PROPERTIES = "javax.jcr.security.Privilege.MODIFY_PROPERTIES";
+
+ /**
+ * A constant representing <code>ADD_CHILD_NODES</code>, the privilege
+ * to create child nodes of a node.
+ */
+ public static final String ADD_CHILD_NODES = "javax.jcr.security.Privilege.ADD_CHILD_NODES";
+
+ /**
+ * A constant representing <code>REMOVE_CHILD_NODES</code>, the privilege
+ * to remove child nodes of a node.
+ */
+ public static final String REMOVE_CHILD_NODES = "javax.jcr.security.Privilege.REMOVE_CHILD_NODES";
+
+ /**
+ * A constant representing <code>WRITE</code>, an aggregate privilege that contains:
+ *<ul>
+ * <li>MODIFY_PROPERTIES</li>
+ * <li>ADD_CHILD_NODES</li>
+ * <li>REMOVE_CHILD_NODES</li>
+ * </ul>
+ */
+ public static final String WRITE = "javax.jcr.security.Privilege.WRITE";
+
+ /**
+ * A constant representing <code>READ_ACCESS_CONTROL</code>, the privilege
+ * to get the access control policy of a node.
+ */
+ public static final String READ_ACCESS_CONTROL = "javax.jcr.security.Privilege.READ_ACCESS_CONTROL";
+
+ /**
+ * A constant representing <code>MODIFY_ACCESS_CONTROL</code>, the privilege
+ * to modify the access control policies of a node.
+ */
+ public static final String MODIFY_ACCESS_CONTROL = "javax.jcr.security.Privilege.MODIFY_ACCESS_CONTROL";
+
+ /**
+ * A constant representing <code>ALL</code>, an aggregate privilege that contains
+ * all predefined privileges:
+ * <ul>
+ * <li>READ</li>
+ * <li>WRITE</li>
+ * <li>READ_ACCESS_CONTROL</li>
+ * <li>MODIFY_ACCESS_CONTROL</li>
+ * </ul>
+ * It should in addition include all implementation-defined privileges.
+ */
+ public static final String ALL = "javax.jcr.security.Privilege.ALL";
+
+ /**
+ * Returns the name of this privilege.
+ *
+ * @return the name of this privilege.
+ */
+ public String getName();
+
+ /**
+ * Returns a description of this privilege.
+ *
+ * @return a description of this privilege.
+ */
+ public String getDescription();
+
+ /**
+ * Returns whether this privilege is an abstract privilege.
+ * @return <code>true</code> if this privilege is an abstract privilege;
+ * <code>false</code> otherwise.
+ */
+ public boolean isAbstract();
+
+ /**
+ * Returns whether this privilege is an aggregate privilege.
+ * @return <code>true</code> if this privilege is an aggregate privilege;
+ * <code>false</code> otherwise.
+ */
+ public boolean isAggregate();
+
+ /**
+ * If this privilege is an aggregate privilege, returns the privileges directly
+ * contained by the aggregate privilege. Otherwise returns an empty array.
+ *
+ * @return an array of <code>Privilege</code>s
+ */
+ public Privilege[] getDeclaredAggregatePrivileges();
+
+ /**
+ * If this privilege is an aggregate privilege, returns the privileges it
+ * contains, the privileges contained by any aggregate privileges among
+ * those, and so on (the transitive closure of privileges contained by this
+ * privilege). Otherwise returns an empty array.
+ *
+ * @return an array of <code>Privilege</code>s
+ */
+ public Privilege[] getAggregatePrivileges();
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/Privilege.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/jsr283/security/Privilege.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url