You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by js...@apache.org on 2024/05/28 08:35:21 UTC
(sling-org-apache-sling-jcr-repoinit) 01/01: SLING-12329 - Backwards compatibility for legacy repoinit statement reordering
This is an automated email from the ASF dual-hosted git repository.
jsedding pushed a commit to branch fix/SLING-12329-legacy-reordering-fallback
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-repoinit.git
commit fd45ec36b8de98334c69661cfd9e50955999060f
Author: Julian Sedding <js...@apache.org>
AuthorDate: Tue May 28 10:35:08 2024 +0200
SLING-12329 - Backwards compatibility for legacy repoinit statement reordering
---
.../repoinit/impl/JcrRepoInitOpsProcessorImpl.java | 72 ++++++++++++++++++----
.../sling/jcr/repoinit/ExecutionOrderTest.java | 45 +++++++++++---
.../org/apache/sling/jcr/repoinit/LogCapture.java | 6 +-
3 files changed, 100 insertions(+), 23 deletions(-)
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/JcrRepoInitOpsProcessorImpl.java b/src/main/java/org/apache/sling/jcr/repoinit/impl/JcrRepoInitOpsProcessorImpl.java
index f0c6981..b072975 100644
--- a/src/main/java/org/apache/sling/jcr/repoinit/impl/JcrRepoInitOpsProcessorImpl.java
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/JcrRepoInitOpsProcessorImpl.java
@@ -17,14 +17,20 @@
package org.apache.sling.jcr.repoinit.impl;
import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
+import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.sling.jcr.repoinit.JcrRepoInitOpsProcessor;
import org.apache.sling.repoinit.parser.operations.Operation;
+import org.apache.sling.repoinit.parser.operations.OperationVisitor;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import static java.util.Arrays.asList;
import static java.util.Collections.singleton;
@@ -38,28 +44,70 @@ import static java.util.Collections.singleton;
})
public class JcrRepoInitOpsProcessorImpl implements JcrRepoInitOpsProcessor {
+ private static final Logger log = LoggerFactory.getLogger(JcrRepoInitOpsProcessorImpl.class);
+
/**
* Apply the supplied operations: first the namespaces and nodetypes
* registrations, then the service users, paths and ACLs.
*/
@Override
public void apply(Session session, List<Operation> ops) {
- Stream.of(
- // register namespaces first
- singleton(new NamespacesVisitor(session)),
- // then create node types and privileges, both use namespaces
- asList(
+ AtomicReference<Operation> lastAttemptedOperation = new AtomicReference<>();
+ try {
+ Stream.of(
+ // register namespaces first
+ singleton(new NamespacesVisitor(session)),
+ // then create node types and privileges, both use namespaces
+ asList(
+ new NodetypesVisitor(session),
+ new PrivilegeVisitor(session)),
+ // finally apply everything else
+ asList(
+ new UserVisitor(session),
+ new NodeVisitor(session),
+ new AclVisitor(session),
+ new GroupMembershipVisitor(session),
+ new NodePropertiesVisitor(session))
+ ).forEach(visitorGroup -> {
+ ops.forEach(op -> {
+ lastAttemptedOperation.set(op);
+ visitorGroup.forEach(op::accept);
+ });
+ });
+ } catch (RepoInitException originalFailure) {
+ // support legacy statement reordering for backwards compatibility
+ try {
+ session.refresh(false); // drop transient changes
+
+ final OperationVisitor[] visitors = {
+ new NamespacesVisitor(session),
new NodetypesVisitor(session),
- new PrivilegeVisitor(session)),
- // finally apply everything else
- asList(
+ new PrivilegeVisitor(session),
new UserVisitor(session),
new NodeVisitor(session),
new AclVisitor(session),
new GroupMembershipVisitor(session),
- new NodePropertiesVisitor(session))
- ).forEach(visitorGroup -> {
- ops.forEach(op -> visitorGroup.forEach(op::accept));
- });
+ new NodePropertiesVisitor(session)
+ };
+
+ for (OperationVisitor v : visitors) {
+ for (Operation op : ops) {
+ op.accept(v);
+ }
+ }
+
+ log.warn("DEPRECATION - The repoinit script being executed relies on a bug causing repoinit " +
+ "statements to be reordered. Please review and fix the ordering of your repoinit statements. " +
+ "The code supporting the legacy order will be removed in a future release. The new code " +
+ "failed on the statement \"{}\"",
+ Optional.ofNullable(lastAttemptedOperation.get()).map(Operation::asRepoInitString).orElse("unknown"));
+ } catch (Exception legacyFailure) {
+ // rethrow the originalFailure if the legacy code also failed
+ throw originalFailure;
+ }
+ }
+
+
+
}
}
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/ExecutionOrderTest.java b/src/test/java/org/apache/sling/jcr/repoinit/ExecutionOrderTest.java
index b27295f..c0f4646 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/ExecutionOrderTest.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/ExecutionOrderTest.java
@@ -16,25 +16,21 @@
*/
package org.apache.sling.jcr.repoinit;
-import org.apache.jackrabbit.api.security.user.Group;
-import org.apache.jackrabbit.api.security.user.UserManager;
+import ch.qos.logback.classic.Level;
import org.apache.sling.jcr.repoinit.impl.TestUtil;
-import org.apache.sling.jcr.repoinit.impl.UserUtil;
import org.apache.sling.repoinit.parser.RepoInitParsingException;
-import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
-import org.apache.sling.testing.mock.sling.junit.SlingContextBuilder;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
-import javax.jcr.Value;
import java.util.UUID;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
/** Verify that namespaces and nodetypes are executed before path creation. But otherwise,
* the execution order should match the order of the statements.
@@ -43,9 +39,9 @@ public class ExecutionOrderTest {
@Rule
public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);
-
+
private TestUtil U;
-
+
private static final String TEST_ID = UUID.randomUUID().toString();
private static final String NS_PREFIX = ExecutionOrderTest.class.getSimpleName();
private static final String NS_URI = "uri:" + NS_PREFIX + ":" + TEST_ID;
@@ -89,4 +85,37 @@ public class ExecutionOrderTest {
U.assertPrivileges(GROUP_NAME, PATH, true, "jcr:read");
U.assertPrivileges(GROUP_NAME, PATH, false, "jcr:write");
}
+
+ @Test
+ public void legacySetAclBeforeCreatingGroupTest() throws Exception {
+ try (LogCapture capture = new LogCapture("org.apache.sling.jcr.repoinit.impl.JcrRepoInitOpsProcessorImpl", true)) {
+ U.parseAndExecute(
+ "create path (nt:folder) " + PATH,
+ "set ACL for " + GROUP_NAME,
+ " allow jcr:read on " + PATH,
+ " deny jcr:write on " + PATH,
+ "end",
+ "create group " + GROUP_NAME
+ );
+
+ capture.assertContains(Level.WARN, "DEPRECATION", "set ACL for " + GROUP_NAME);
+ } catch (RuntimeException e) {
+ fail("Legacy support should have reordered \"create group\" before \"set ACL\"");
+ }
+ }
+
+ @Test
+ public void legacyAddMemberBeforeCreatingGroupTest() throws Exception {
+ try (LogCapture capture = new LogCapture("org.apache.sling.jcr.repoinit.impl.JcrRepoInitOpsProcessorImpl", true)) {
+ U.parseAndExecute(
+ "create group " + GROUP_NAME + "_1",
+ "add " + GROUP_NAME + "_1 to group " + GROUP_NAME,
+ "create group " + GROUP_NAME // reordered by legacy code
+ );
+
+ capture.assertContains(Level.WARN, "DEPRECATION", "add " + GROUP_NAME + "_1 to group ");
+ } catch (RuntimeException e) {
+ fail("Legacy support should have reordered \"create group\" before \"add ... to group\"");
+ }
+ }
}
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/LogCapture.java b/src/test/java/org/apache/sling/jcr/repoinit/LogCapture.java
index 8a4a5e4..153664f 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/LogCapture.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/LogCapture.java
@@ -31,9 +31,9 @@ import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;
-/**
- * Capture logs for testing
- *
+/**
+ * Capture logs for testing
+ *
* Initially cloned from: https://github.com/apache/sling-org-apache-sling-graphql-core/blob/0b1c1dd72ed04324ea84d2227c3223ec65b0b21e/src/test/java/org/apache/sling/graphql/core/util/LogCapture.java
*/
class LogCapture extends ListAppender<ILoggingEvent> implements AutoCloseable {