Allow to provide LogHandlers as Services via java.util.ServiceLoader.
MODIFY
asciidoctorj-core/src/main/java/org/asciidoctor/internal/JRubyAsciidoctor.java
asciidoctorj-core/src/main/java/org/asciidoctor/internal/JRubyAsciidoctor.java
@@ -22,6 +22,7 @@ import org.asciidoctor.log.LogHandler;
import org.asciidoctor.log.LogRecord;
import org.asciidoctor.log.internal.JULLogHandler;
import org.asciidoctor.log.internal.JavaLogger;
+import org.asciidoctor.log.internal.LogHandlerRegistryExecutor;
import org.jruby.CompatVersion;
import org.jruby.Ruby;
import org.jruby.RubyHash;
@@ -82,7 +83,7 @@ public class JRubyAsciidoctor implements Asciidoctor, LogHandler {
Asciidoctor asciidoctor = createJRubyAsciidoctorInstance(env);
registerExtensions(asciidoctor);
registerConverters(asciidoctor);
-
+ registerLogHandlers(asciidoctor);
return asciidoctor;
}
@@ -100,6 +101,7 @@ public class JRubyAsciidoctor implements Asciidoctor, LogHandler {
return asciidoctor;
}
+
public static Asciidoctor create(ClassLoader classloader, String gemPath) {
Asciidoctor asciidoctor = createJRubyAsciidoctorInstance(classloader, gemPath);
registerExtensions(asciidoctor);
@@ -116,6 +118,10 @@ public class JRubyAsciidoctor implements Asciidoctor, LogHandler {
new ExtensionRegistryExecutor(asciidoctor).registerAllExtensions();
}
+ private static void registerLogHandlers(Asciidoctor asciidoctor) {
+ new LogHandlerRegistryExecutor(asciidoctor).registerAllLogHandlers();
+ }
+
private static Asciidoctor createJRubyAsciidoctorInstance(List<String> loadPaths) {
RubyInstanceConfig config = createOptimizedConfiguration();
@@ -150,6 +156,7 @@ public class JRubyAsciidoctor implements Asciidoctor, LogHandler {
JRubyAsciidoctor jRubyAsciidoctor = new JRubyAsciidoctor(asciidoctorModule, rubyRuntime);
JavaLogger.install(rubyRuntime, jRubyAsciidoctor);
+
return jRubyAsciidoctor;
}

ADD
asciidoctorj-core/src/main/java/org/asciidoctor/log/internal/LogHandlerRegistryExecutor.java
+package org.asciidoctor.log.internal;
+
+import org.asciidoctor.Asciidoctor;
+import org.asciidoctor.log.LogHandler;
+
+import java.util.ServiceLoader;
+
+public class LogHandlerRegistryExecutor {
+ private static ServiceLoader<LogHandler> logHandlerServiceLoader = ServiceLoader
+ .load(LogHandler.class);
+
+ private Asciidoctor asciidoctor;
+
+ public LogHandlerRegistryExecutor(Asciidoctor asciidoctor) {
+ this.asciidoctor = asciidoctor;
+ }
+
+ public void registerAllLogHandlers() {
+ for (LogHandler logHandler: logHandlerServiceLoader) {
+ asciidoctor.registerLogHandler(logHandler);
+ }
+ }
+
+}

MODIFY
asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciidoctorLogsToConsole.java
asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciidoctorLogsToConsole.java
@@ -4,6 +4,7 @@ import org.asciidoctor.ast.Cursor;
import org.asciidoctor.internal.JRubyAsciidoctor;
import org.asciidoctor.log.LogHandler;
import org.asciidoctor.log.LogRecord;
+import org.asciidoctor.log.TestLogHandlerService;
import org.asciidoctor.util.ClasspathResources;
import org.junit.After;
import org.junit.Before;
@@ -45,6 +46,7 @@ public class WhenAsciidoctorLogsToConsole {
@After
public void cleanup() throws IOException {
LogManager.getLogManager().readConfiguration();
+ TestLogHandlerService.clear();
}
@Test
@@ -117,6 +119,37 @@ public class WhenAsciidoctorLogsToConsole {
}
+ @Test
+ public void shouldNotifyLogHandlerService() throws Exception {
+
+ File inputFile = classpath.getResource("documentwithnotexistingfile.adoc");
+ String renderContent = asciidoctor.renderFile(inputFile,
+ options()
+ .inPlace(true)
+ .safe(SafeMode.SERVER)
+ .attributes(
+ AttributesBuilder.attributes().allowUriRead(true))
+ .asMap());
+
+ File expectedFile = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
+ expectedFile.delete();
+
+ final List<LogRecord> logRecords = TestLogHandlerService.getLogRecords();
+ assertEquals(4, logRecords.size());
+ assertThat(logRecords.get(0).getMessage(), containsString("include file not found"));
+ final Cursor cursor = (Cursor) logRecords.get(0).getCursor();
+ assertThat(cursor.getDir().replace('\\', '/'), is(inputFile.getParent().replace('\\', '/')));
+ assertThat(cursor.getFile(), is(inputFile.getName()));
+ assertThat(cursor.getLineNumber(), is(3));
+
+ for (LogRecord logRecord: logRecords) {
+ assertThat(logRecord.getCursor(), not(nullValue()));
+ assertThat(logRecord.getCursor().getFile(), not(nullValue()));
+ assertThat(logRecord.getCursor().getDir(), not(nullValue()));
+ }
+
+ }
+
@Test
public void shouldOnlyNotifyFromRegisteredAsciidoctor() throws Exception {

ADD
asciidoctorj-core/src/test/java/org/asciidoctor/log/TestLogHandlerService.java
+package org.asciidoctor.log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestLogHandlerService implements LogHandler {
+
+ private static List<LogRecord> logRecords = new ArrayList<>();
+
+ public static List<LogRecord> getLogRecords() {
+ return logRecords;
+ }
+
+ public static void clear() {
+ logRecords.clear();
+ }
+
+ @Override
+ public void log(LogRecord logRecord) {
+ logRecords.add(logRecord);
+ }
+}

ADD
asciidoctorj-core/src/test/resources/META-INF/services/org.asciidoctor.log.LogHandler
+org.asciidoctor.log.TestLogHandlerService
\ No newline at end of file

Allow to provide LogHandlers as Services via java.util.ServiceLoader.