Author: angela
Date: Tue Nov 22 17:46:45 2016
New Revision: 1770863
URL: http://svn.apache.org/viewvc?rev=1770863&view=rev
Log:
OAK-5025 : Speed up ACE node name generation
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/UtilTest.java
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authorization/
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authorization/AceCreationTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/Util.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImplTest.java
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java?rev=1770863&r1=1770862&r2=1770863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java
Tue Nov 22 17:46:45 2016
@@ -280,10 +280,11 @@ public class AccessControlManagerImpl ex
aclTree = createAclTree(oakPath, tree);
}
aclTree.setOrderableChildren(true);
- for (ACE ace : acl.getEntries()) {
- boolean isAllow = ace.isAllow();
- String nodeName = Util.generateAceName(aclTree, isAllow);
- String ntName = (isAllow) ? NT_REP_GRANT_ACE : NT_REP_DENY_ACE;
+ List<ACE> entries = acl.getEntries();
+ for (int i = 0; i < entries.size(); i++) {
+ ACE ace = entries.get(i);
+ String nodeName = Util.generateAceName(ace, i);
+ String ntName = (ace.isAllow()) ? NT_REP_GRANT_ACE :
NT_REP_DENY_ACE;
NodeUtil aceNode = new NodeUtil(aclTree).addChild(nodeName,
ntName);
aceNode.setString(REP_PRINCIPAL_NAME,
ace.getPrincipal().getName());
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/Util.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/Util.java?rev=1770863&r1=1770862&r2=1770863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/Util.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/Util.java
Tue Nov 22 17:46:45 2016
@@ -27,6 +27,7 @@ import org.apache.jackrabbit.api.securit
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
import
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.ACE;
import
org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
@@ -113,22 +114,20 @@ final class Util implements AccessContro
}
/**
- * Create a unique valid name for the Permission nodes to be save.
+ * Create a valid name for the ACE node based on the entry and it's index.
*
- * @param aclTree The acl for which a new ACE name should be generated.
- * @param isAllow If the ACE is allowing or denying.
+ * @param ace The access control entry.
+ * @param index The index of the entry in the list
* @return the name of the ACE node.
*/
@Nonnull
- public static String generateAceName(@Nonnull Tree aclTree, boolean
isAllow) {
- int i = 0;
- String hint = (isAllow) ? "allow" : "deny";
- String aceName = hint;
- while (aclTree.hasChild(aceName)) {
- aceName = hint + i;
- i++;
+ public static String generateAceName(@Nonnull ACE ace, int index) {
+ String hint = (ace.isAllow()) ? "allow" : "deny";
+ if (index == 0) {
+ return hint;
+ } else {
+ return hint + index;
}
- return aceName;
}
public static int getImportBehavior(AuthorizationConfiguration config) {
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImplTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImplTest.java?rev=1770863&r1=1770862&r2=1770863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImplTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImplTest.java
Tue Nov 22 17:46:45 2016
@@ -44,10 +44,12 @@ import javax.jcr.security.AccessControlP
import javax.jcr.security.AccessControlPolicyIterator;
import javax.jcr.security.Privilege;
+import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
@@ -1396,6 +1398,65 @@ public class AccessControlManagerImplTes
}
}
+ @Test
+ public void testSetPolicyModifiesRoot() throws Exception {
+ ACL acl = getApplicablePolicy(testPath);
+ assertTrue(acl.addAccessControlEntry(testPrincipal, testPrivileges));
+ assertFalse(root.hasPendingChanges());
+
+ acMgr.setPolicy(testPath, acl);
+ assertTrue(root.hasPendingChanges());
+
+ root.commit();
+
+ acl = (ACL) acMgr.getPolicies(testPath)[0];
+ assertEquals(1, acl.getAccessControlEntries().length);
+
+ acl.addEntry(EveryonePrincipal.getInstance(), testPrivileges, false,
getGlobRestriction("*/something"));
+ acMgr.setPolicy(testPath, acl);
+ assertTrue(root.hasPendingChanges());
+
+ root.commit();
+
+ acl = (ACL) acMgr.getPolicies(testPath)[0];
+ assertEquals(2, acl.getAccessControlEntries().length);
+ }
+
+ @Test
+ public void testSetPolicyWithRestrictions() throws Exception {
+ ACL acl = getApplicablePolicy(testPath);
+ acl.addEntry(testPrincipal, testPrivileges, true,
ImmutableMap.of(AccessControlConstants.REP_GLOB,
getValueFactory().createValue("/a/b")));
+ acl.addEntry(testPrincipal, testPrivileges, true,
ImmutableMap.of(AccessControlConstants.REP_GLOB,
getValueFactory().createValue("/c/d")));
+ acMgr.setPolicy(testPath, acl);
+ root.commit();
+
+ ACL l = (ACL) acMgr.getPolicies(testPath)[0];
+ assertEquals(2, l.getAccessControlEntries().length);
+ }
+
+ @Test
+ public void testSetPolicyCreatesIndexedAceNodeNames() throws Exception {
+ ACL acl = getApplicablePolicy(testPath);
+ assertTrue(acl.addAccessControlEntry(testPrincipal, testPrivileges));
+ assertTrue(acl.addEntry(testPrincipal, testPrivileges, true,
ImmutableMap.of(AccessControlConstants.REP_GLOB,
getValueFactory().createValue("/*/a"))));
+ assertTrue(acl.addEntry(EveryonePrincipal.getInstance(),
testPrivileges, false));
+ assertTrue(acl.addEntry(EveryonePrincipal.getInstance(),
testPrivileges, false, ImmutableMap.of(AccessControlConstants.REP_GLOB,
getValueFactory().createValue("/*/a"))));
+ acMgr.setPolicy(testPath, acl);
+ root.commit();
+
+ acl = (ACL) acMgr.getPolicies(testPath)[0];
+ assertEquals(4, acl.getAccessControlEntries().length);
+
+ Iterable<Tree> aceTrees =
root.getTree(testPath).getChild(AccessControlConstants.REP_POLICY).getChildren();
+ String[] aceNodeNames =
Iterables.toArray(Iterables.transform(aceTrees, new Function<Tree, String>() {
+ @Override
+ public String apply(Tree aceTree) {
+ return aceTree.getName();
+ }
+ }), String.class);
+ assertArrayEquals(new String[]{"allow", "allow1", "deny2", "deny3"},
aceNodeNames);
+ }
+
//--------------------------< removePolicy(String, AccessControlPolicy)
>---
@Test
public void testRemovePolicy() throws Exception {
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/UtilTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/UtilTest.java?rev=1770863&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/UtilTest.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/UtilTest.java
Tue Nov 22 17:46:45 2016
@@ -0,0 +1,109 @@
+/*
+ * 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.oak.security.authorization.accesscontrol;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlException;
+import javax.jcr.security.Privilege;
+
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.ACE;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+public class UtilTest extends AbstractSecurityTest {
+
+ private static final String DENY = "deny";
+ private static final String ALLOW = "allow";
+
+ private PrivilegeBitsProvider bitsProvider;
+
+ @Override
+ @Before
+ public void before() throws Exception {
+ super.before();
+
+ bitsProvider = new PrivilegeBitsProvider(root);
+ }
+
+ @Test
+ public void testGenerateName() throws AccessControlException {
+ ACE ace = new TestAce(true);
+ String name = Util.generateAceName(ace, 0);
+
+ assertTrue(name.startsWith(ALLOW));
+ assertEquals(ALLOW, name);
+ assertEquals(name, Util.generateAceName(ace, 0));
+
+ name = Util.generateAceName(ace, 1);
+ assertTrue(name.startsWith(ALLOW));
+ assertEquals(ALLOW + 1, name);
+ assertEquals(name, Util.generateAceName(ace, 1));
+ }
+
+ @Test
+ public void testGenerateName2() throws AccessControlException {
+ ACE ace = new TestAce(false);
+ String name = Util.generateAceName(ace, 0);
+
+ assertTrue(name.startsWith(DENY));
+ assertEquals(DENY, name);
+ assertEquals(name, Util.generateAceName(ace, 0));
+
+ name = Util.generateAceName(ace, 2);
+ assertTrue(name.startsWith(DENY));
+ assertEquals(DENY + 2, name);
+ assertEquals(name, Util.generateAceName(ace, 2));
+ }
+
+ @Test
+ public void testGenerateNameDifferentAllow() throws Exception {
+ ACE allow = new TestAce(false);
+ ACE deny = new TestAce(true);
+
+ assertNotEquals(Util.generateAceName(allow, 0),
Util.generateAceName(deny, 0));
+ assertNotEquals(Util.generateAceName(allow, 1),
Util.generateAceName(deny, 1));
+ assertNotEquals(Util.generateAceName(allow, 20),
Util.generateAceName(deny, 20));
+ assertNotEquals(Util.generateAceName(allow, 0),
Util.generateAceName(deny, 1));
+ assertNotEquals(Util.generateAceName(allow, 1),
Util.generateAceName(deny, 20));
+
+ }
+
+ private final class TestAce extends ACE {
+
+ public TestAce(boolean isAllow) throws AccessControlException {
+ super(EveryonePrincipal.getInstance(),
bitsProvider.getBits(PrivilegeConstants.JCR_READ), isAllow, null,
NamePathMapper.DEFAULT);
+ }
+
+ @Override
+ public Privilege[] getPrivileges() {
+ try {
+ return
privilegesFromNames(bitsProvider.getPrivilegeNames(getPrivilegeBits()));
+ } catch (RepositoryException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+ }
+}
Modified:
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java?rev=1770863&r1=1770862&r2=1770863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
(original)
+++
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
Tue Nov 22 17:46:45 2016
@@ -42,6 +42,7 @@ import org.apache.commons.io.FileUtils;
import
org.apache.jackrabbit.oak.benchmark.authentication.external.ExternalLoginTest;
import
org.apache.jackrabbit.oak.benchmark.authentication.external.SyncAllExternalUsersTest;
import
org.apache.jackrabbit.oak.benchmark.authentication.external.SyncExternalUsersTest;
+import org.apache.jackrabbit.oak.benchmark.authorization.AceCreationTest;
import org.apache.jackrabbit.oak.benchmark.wikipedia.WikipediaImport;
import org.apache.jackrabbit.oak.fixture.JackrabbitRepositoryFixture;
import org.apache.jackrabbit.oak.fixture.OakFixture;
@@ -116,6 +117,8 @@ public class BenchmarkRunner {
.withOptionalArg().ofType(Long.class).defaultsTo(AbstractLoginTest.NO_CACHE);
OptionSpec<Integer> numberOfGroups = parser.accepts("numberOfGroups",
"Number of groups to create.")
.withOptionalArg().ofType(Integer.class).defaultsTo(LoginWithMembershipTest.NUMBER_OF_GROUPS_DEFAULT);
+ OptionSpec<Integer> numberOfInitialAce =
parser.accepts("numberOfInitialAce", "Number of ACE to create before running
the test.")
+
.withOptionalArg().ofType(Integer.class).defaultsTo(AceCreationTest.NUMBER_OF_INITIAL_ACE_DEFAULT);
OptionSpec<Boolean> nestedGroups = parser.accepts("nestedGroups", "Use
nested groups.")
.withOptionalArg().ofType(Boolean.class).defaultsTo(false);
OptionSpec<Integer> batchSize = parser.accepts("batchSize", "Batch
size before persisting operations.")
@@ -150,6 +153,9 @@ public class BenchmarkRunner {
.withOptionalArg().ofType(Boolean.class).defaultsTo(Boolean.FALSE);
OptionSpec<String> autoMembership = parser.accepts("autoMembership",
"Ids of those groups a given external identity automatically become member of.")
.withOptionalArg().ofType(String.class).withValuesSeparatedBy(',');
+ OptionSpec<Boolean> transientWrites = parser.accepts("transient", "Do
not save data.")
+ .withOptionalArg().ofType(Boolean.class)
+ .defaultsTo(Boolean.FALSE);
OptionSpec<String> nonOption = parser.nonOptions();
OptionSpec help = parser.acceptsAll(asList("h", "?", "help"), "show
help").forHelp();
OptionSet options = parser.parse(args);
@@ -325,6 +331,8 @@ public class BenchmarkRunner {
randomUser.value(options)),
new ConcurrentWriteACLTest(itemsToRead.value(options)),
new ConcurrentEveryoneACLTest(runAsAdmin.value(options),
itemsToRead.value(options)),
+ new AceCreationTest(batchSize.value(options),
numberOfInitialAce.value(options), transientWrites.value(options)),
+
ReadManyTest.linear("LinearReadEmpty", 1, ReadManyTest.EMPTY),
ReadManyTest.linear("LinearReadFiles", 1, ReadManyTest.FILES),
ReadManyTest.linear("LinearReadNodes", 1, ReadManyTest.NODES),
Added:
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authorization/AceCreationTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authorization/AceCreationTest.java?rev=1770863&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authorization/AceCreationTest.java
(added)
+++
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authorization/AceCreationTest.java
Tue Nov 22 17:46:45 2016
@@ -0,0 +1,130 @@
+package org.apache.jackrabbit.oak.benchmark.authorization;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import
org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.benchmark.AbstractTest;
+import org.apache.jackrabbit.oak.spi.security.authentication.SystemSubject;
+import
org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.Privilege;
+import javax.security.auth.Subject;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Random;
+
+public class AceCreationTest extends AbstractTest {
+
+ public static final int NUMBER_OF_INITIAL_ACE_DEFAULT = 0;
+ private final int numberOfAce;
+ private final int numberOfInitialAce;
+ private final boolean transientWrites;
+ private String nodePath;
+
+ private Session transientSession;
+
+ public AceCreationTest(int numberOfAce, int numberOfInitialAce, boolean
transientWrites) {
+ super();
+ this.numberOfAce = numberOfAce;
+ this.numberOfInitialAce = numberOfInitialAce;
+ this.transientWrites = transientWrites;
+ }
+
+ @Override
+ protected void beforeSuite() throws Exception {
+ super.beforeSuite();
+
+ Session session = createOrGetSystemSession();
+ nodePath = session.getRootNode().addNode("test" + new
Random().nextInt()).getPath();
+
+ save(session, transientWrites);
+ logout(session, transientWrites);
+ }
+
+ @Override
+ protected void beforeTest() throws Exception {
+ super.beforeTest();
+
+ Session session = createOrGetSystemSession();
+ createAce(session, numberOfInitialAce);
+
+ save(session, transientWrites);
+ logout(session, transientWrites);
+ }
+
+ @Override
+ protected void afterTest() throws Exception {
+ Session session = createOrGetSystemSession();
+
+ AccessControlManager acm = session.getAccessControlManager();
+ for (AccessControlPolicy policy : acm.getPolicies(nodePath)) {
+ acm.removePolicy(nodePath, policy);
+ }
+ save(session, transientWrites);
+
+ super.afterTest();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ try {
+ if (transientSession != null) {
+ transientSession.logout();
+ }
+ } finally {
+ super.tearDown();
+ }
+ }
+
+ @Override
+ protected void runTest() throws Exception {
+ Session session = createOrGetSystemSession();
+
+ createAce(session, numberOfAce);
+ save(session, transientWrites);
+ logout(session, transientWrites);
+ }
+
+ private void createAce(Session session, int count) throws
RepositoryException {
+ AccessControlManager acManager = session.getAccessControlManager();
+ JackrabbitAccessControlList acl =
AccessControlUtils.getAccessControlList(acManager, nodePath);
+
+ for (int i = 0; i < count; i++) {
+ ImmutableMap<String, Value> restrictions =
ImmutableMap.of(AccessControlConstants.REP_GLOB,
session.getValueFactory().createValue(i + ""));
+ acl.addEntry(EveryonePrincipal.getInstance(),
AccessControlUtils.privilegesFromNames(acManager,
Privilege.JCR_ADD_CHILD_NODES), true, restrictions);
+ }
+
+ acManager.setPolicy(nodePath, acl);
+ }
+
+ private static void save(Session session, boolean transientWrites) throws
RepositoryException {
+ if (!transientWrites) {
+ session.save();
+ }
+ }
+
+ private static void logout(Session session, boolean transientWrites) {
+ if (!transientWrites) {
+ session.logout();
+ }
+ }
+
+ private Session createOrGetSystemSession() throws
PrivilegedActionException {
+ if(transientWrites && transientSession != null) {
+ return transientSession;
+ }
+
+ return (transientSession =
Subject.doAsPrivileged(SystemSubject.INSTANCE, new
PrivilegedExceptionAction<Session>() {
+ @Override
+ public Session run() throws Exception {
+ return getRepository().login(null, null);
+ }
+ }, null));
+ }
+}