diff --git a/spring-geode-starter-logging/src/main/java/org/springframework/geode/logging/slf4j/logback/DelegatingAppender.java b/spring-geode-starter-logging/src/main/java/org/springframework/geode/logging/slf4j/logback/DelegatingAppender.java new file mode 100644 index 00000000..32eabecf --- /dev/null +++ b/spring-geode-starter-logging/src/main/java/org/springframework/geode/logging/slf4j/logback/DelegatingAppender.java @@ -0,0 +1,68 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed 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 + * + * https://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.springframework.geode.logging.slf4j.logback; + +import java.util.Objects; +import java.util.Optional; + +import org.slf4j.LoggerFactory; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.helpers.NOPAppender; + +/** + * {@link DelegatingAppender} is an SLF4J {@link Appender} that delegates to the configured {@link Appender}. + * + * If no {@link Appender} was configured, then the {@link DelegatingAppender} delegates to the {@link NOPAppender}. + * + * @author John Blum + * @see ch.qos.logback.core.Appender + * @see ch.qos.logback.core.AppenderBase + * @see ch.qos.logback.core.helpers.NOPAppender + * @since 1.3.0 + */ +public class DelegatingAppender extends AppenderBase { + + @SuppressWarnings("rawtypes") + protected static final Appender defaultAppender = new NOPAppender<>(); + + public DelegatingAppender() { + + Optional.ofNullable(LoggerFactory.getILoggerFactory()) + .filter(it -> Objects.isNull(defaultAppender.getContext())) + .filter(Context.class::isInstance) + .map(Context.class::cast) + .ifPresent(defaultAppender::setContext); + } + + private volatile Appender appender; + + public void setAppender(Appender appender) { + this.appender = appender; + } + + @SuppressWarnings("unchecked") + protected Appender getAppender() { + return Optional.ofNullable(this.appender).orElse(defaultAppender); + } + + @Override + protected void append(T eventObject) { + getAppender().doAppend(eventObject); + } +} diff --git a/spring-geode-starter-logging/src/test/java/org/springframework/geode/logging/slf4j/logback/DelegatingAppenderUnitTests.java b/spring-geode-starter-logging/src/test/java/org/springframework/geode/logging/slf4j/logback/DelegatingAppenderUnitTests.java new file mode 100644 index 00000000..04263ee3 --- /dev/null +++ b/spring-geode-starter-logging/src/test/java/org/springframework/geode/logging/slf4j/logback/DelegatingAppenderUnitTests.java @@ -0,0 +1,62 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed 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 + * + * https://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.springframework.geode.logging.slf4j.logback; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.Test; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.helpers.NOPAppender; + +/** + * Unit Tests for {@link DelegatingAppender}. + * + * @author John Blum + * @see org.junit.Test + * @see org.mockito.Mock + * @see org.mockito.Mockito + * @see org.springframework.geode.logging.slf4j.logback.DelegatingAppender + * @since 1.3.0 + */ +public class DelegatingAppenderUnitTests { + + @Test + public void delegatingAppenderDefaultsToNoOpAppender() { + assertThat(new DelegatingAppender<>().getAppender()).isInstanceOf(NOPAppender.class); + } + + @Test + @SuppressWarnings({ "rawtypes", "unchecked" }) + public void delegatingAppenderDelegatesToMockAppender() { + + Appender mockAppender = mock(Appender.class); + + DelegatingAppender delegatingAppender = new DelegatingAppender<>(); + + delegatingAppender.setAppender(mockAppender); + + assertThat(delegatingAppender.getAppender()).isSameAs(mockAppender); + + delegatingAppender.append("TEST"); + + verify(mockAppender, times(1)).doAppend(eq("TEST")); + } +}