diff --git a/pom.xml b/pom.xml
index 4bdc797..0fa5076 100644
--- a/pom.xml
+++ b/pom.xml
@@ -188,12 +188,12 @@
slf4j-api
provided
-
- org.slf4j
- slf4j-log4j12
- 1.7.30
- test
-
+
+ ch.qos.logback
+ logback-classic
+ 1.2.3
+ test
+
javax.jcr
jcr
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/RepositoryInitializerFactory.java b/src/main/java/org/apache/sling/jcr/repoinit/impl/RepositoryInitializerFactory.java
index 8d30330..731388a 100644
--- a/src/main/java/org/apache/sling/jcr/repoinit/impl/RepositoryInitializerFactory.java
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/RepositoryInitializerFactory.java
@@ -16,6 +16,7 @@
*/
package org.apache.sling.jcr.repoinit.impl;
+import java.io.IOException;
import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
@@ -28,6 +29,7 @@
import org.apache.sling.jcr.api.SlingRepositoryInitializer;
import org.apache.sling.jcr.repoinit.JcrRepoInitOpsProcessor;
import org.apache.sling.repoinit.parser.RepoInitParser;
+import org.apache.sling.repoinit.parser.RepoInitParsingException;
import org.apache.sling.repoinit.parser.operations.Operation;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Activate;
@@ -73,6 +75,8 @@ public class RepositoryInitializerFactory implements SlingRepositoryInitializer
String[] scripts() default {};
}
+ protected static final String PROPERTY_FAIL_ON_ERROR = "org.apache.sling.jcr.repoinit.failOnError";
+
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -87,7 +91,11 @@ public class RepositoryInitializerFactory implements SlingRepositoryInitializer
@Activate
public void activate(final RepositoryInitializerFactory.Config config) {
this.config = config;
- log.debug("Activated: {}", this.toString());
+ if (continueOnError()) {
+ log.info("Activated: {} (continue on repoinit errors)", this);
+ } else {
+ log.debug("Activated: {}", this.toString());
+ }
}
@Override
@@ -99,43 +107,50 @@ public String toString() {
@Override
public void processRepository(final SlingRepository repo) throws Exception {
- if ( (config.references() != null && config.references().length > 0)
- || (config.scripts() != null && config.scripts().length > 0 )) {
+ // loginAdministrative is ok here, definitely an admin operation
+ final Session s = repo.loginAdministrative(null);
+ try {
+ executeScripts(s, config);
+ } catch (Exception e) {
+ if (continueOnError()) {
+ log.error("Repoinit error, won't stop execution because {} is set to non-true. Without this "
+ + "setting the startup would fail.",PROPERTY_FAIL_ON_ERROR,e);
+ } else {
+ throw (e);
+ }
+ } finally {
+ s.logout();
+ }
+ }
- // loginAdministrative is ok here, definitely an admin operation
- final Session s = repo.loginAdministrative(null);
- try {
- if ( config.references() != null ) {
- final RepoinitTextProvider p = new RepoinitTextProvider();
- for(final String reference : config.references()) {
- if(reference == null || reference.trim().length() == 0) {
- continue;
- }
- final String repoinitText = p.getRepoinitText("raw:" + reference);
- final List ops = parser.parse(new StringReader(repoinitText));
- String msg = String.format("Executing %s repoinit operations", ops.size());
- log.info(msg);
- applyOperations(s,ops,msg);
- }
+
+ protected void executeScripts (Session session, RepositoryInitializerFactory.Config config) throws IOException, RepositoryException, RepoInitParsingException {
+ if (config.references() != null) {
+ final RepoinitTextProvider p = new RepoinitTextProvider();
+ for (final String reference : config.references()) {
+ if (reference == null || reference.trim().length() == 0) {
+ continue;
}
- if ( config.scripts() != null ) {
- for(final String script : config.scripts()) {
- if(script == null || script.trim().length() == 0) {
- continue;
- }
- final List ops = parser.parse(new StringReader(script));
- String msg = String.format("Executing %s repoinit operations", ops.size());
- log.info(msg);
- applyOperations(s,ops,msg);
- }
+ final String repoinitText = p.getRepoinitText("raw:" + reference);
+ final List ops = parser.parse(new StringReader(repoinitText));
+ String msg = String.format("Executing %s repoinit operations", ops.size());
+ log.info(msg);
+ applyOperations(session, ops, msg);
+ }
+ }
+ if (config.scripts() != null) {
+ for (final String script : config.scripts()) {
+ if (script == null || script.trim().length() == 0) {
+ continue;
}
- } finally {
- s.logout();
+ final List ops = parser.parse(new StringReader(script));
+ String msg = String.format("Executing %s repoinit operations", ops.size());
+ log.info(msg);
+ applyOperations(session, ops, msg);
}
}
}
-
/**
* Apply the operations within a session, support retries
* @param session the JCR session to use
@@ -177,5 +192,10 @@ protected void applyOperations(Session session, List ops, String logM
}
}
+
+ protected boolean continueOnError() {
+ String failOnError = System.getProperty(PROPERTY_FAIL_ON_ERROR,"true");
+ return !failOnError.equals("true");
+ }
}
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/impl/RepositoryInitializerFactoryTest.java b/src/test/java/org/apache/sling/jcr/repoinit/impl/RepositoryInitializerFactoryTest.java
index ac69d7c..37d5f04 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/impl/RepositoryInitializerFactoryTest.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/impl/RepositoryInitializerFactoryTest.java
@@ -16,25 +16,33 @@
*/
package org.apache.sling.jcr.repoinit.impl;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+
+import java.util.Properties;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.repoinit.JcrRepoInitOpsProcessor;
+import org.apache.sling.jcr.repoinit.impl.util.LogCapture;
import org.apache.sling.repoinit.parser.RepoInitParser;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-
import org.mockito.ArgumentMatchers;
+import org.mockito.Mockito;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
+import ch.qos.logback.classic.Level;
public class RepositoryInitializerFactoryTest {
@Rule
- public SlingContext context = new SlingContext();
+ public SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);
RepositoryInitializerFactory sut;
JcrRepoInitOpsProcessor processor;
@@ -56,4 +64,20 @@ public void handleUncheckedErrorsInOperations() throws RepositoryException {
.when(processor).apply(ArgumentMatchers.any(), ArgumentMatchers.any());
sut.applyOperations(mock(Session.class), null, null);
}
+
+ @Test
+ public void validateDeveloperMode() throws Exception {
+
+ Properties oldProps = System.getProperties();
+ try (LogCapture capture = new LogCapture(RepositoryInitializerFactory.class.getName(),true);){
+ System.setProperty(RepositoryInitializerFactory.PROPERTY_FAIL_ON_ERROR, "false");
+ RepositoryInitializerFactory spy = Mockito.spy(sut);
+ doThrow(new RepositoryException("reason")).when(spy).executeScripts(any(Session.class),any(RepositoryInitializerFactory.Config.class));
+ spy.processRepository(context.getService(SlingRepository.class));
+ capture.assertContains(Level.ERROR, "Repoinit error, won't stop execution");
+ } finally {
+ System.clearProperty(RepositoryInitializerFactory.PROPERTY_FAIL_ON_ERROR);
+ }
+ }
+
}
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/impl/util/LogCapture.java b/src/test/java/org/apache/sling/jcr/repoinit/impl/util/LogCapture.java
new file mode 100644
index 0000000..6e59896
--- /dev/null
+++ b/src/test/java/org/apache/sling/jcr/repoinit/impl/util/LogCapture.java
@@ -0,0 +1,70 @@
+/*
+ * 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.sling.jcr.repoinit.impl.util;
+
+import static org.junit.Assert.fail;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.read.ListAppender;
+
+/** Capture logs for testing */
+public class LogCapture extends ListAppender implements Closeable {
+ private final boolean verboseFailure;
+
+ /** Setup the capture and start it */
+ public LogCapture(String loggerName, boolean verboseFailure) {
+ this.verboseFailure = verboseFailure;
+ Logger logger = (Logger) LoggerFactory.getLogger(loggerName);
+ logger.setLevel(Level.ALL);
+ setContext((LoggerContext) LoggerFactory.getILoggerFactory());
+ logger.addAppender(this);
+ start();
+ }
+
+ public boolean anyMatch(Predicate p) {
+ return this.list.stream().anyMatch(p);
+ }
+
+ public void assertContains(Level atLevel, String ... substrings) {
+ Stream.of(substrings).forEach(substring -> {
+ if(!anyMatch(event -> event.getLevel() == atLevel && event.getFormattedMessage().contains(substring))) {
+ if(verboseFailure) {
+ fail(String.format("No log message contains [%s] in log\n%s", substring, this.list.toString()));
+ } else {
+ fail(String.format("No log message contains [%s]", substring));
+ }
+ }
+ });
+ }
+
+ @Override
+ public void close() throws IOException {
+ stop();
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties
deleted file mode 100644
index 3060198..0000000
--- a/src/test/resources/log4j.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-# 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.
-
-log4j.rootLogger=INFO, file
-log4j.appender.file=org.apache.log4j.FileAppender
-log4j.appender.file.File=target/testing.log
-log4j.appender.file.layout=org.apache.log4j.PatternLayout
-log4j.appender.file.layout.ConversionPattern=%d{dd.MM.yyyy HH:mm:ss} *%-5p* [%t] %c{1}: %m (%F, line %L)\n
-
-log4j.logger.org.apache.jackrabbit=WARN
\ No newline at end of file
diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml
new file mode 100644
index 0000000..9d7162a
--- /dev/null
+++ b/src/test/resources/logback.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file