com.diffplug.spotless.extra.eclipse.base.service.SingleSlf4JService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spotless-eclipse-base Show documentation
Show all versions of spotless-eclipse-base Show documentation
Eclipse bundle controller and services for Spotless
/*
* Copyright 2016 DiffPlug
*
* 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
*
* 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 com.diffplug.spotless.extra.eclipse.base.service;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import org.eclipse.core.internal.runtime.InternalPlatform;
import org.eclipse.equinox.log.ExtendedLogReaderService;
import org.eclipse.equinox.log.ExtendedLogService;
import org.eclipse.equinox.log.LogFilter;
import org.eclipse.equinox.log.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogLevel;
import org.osgi.service.log.LogListener;
import org.osgi.service.log.LoggerConsumer;
/**
* Eclipse log service facade that delegates to a Slf4J logger.
* The service does not provide historical log entries (empty history reported).
* No factory service is provided for OSGI logger extensions (method are marked
* as deprecated and raise UnsupportedOperationException).
* All Eclipse logger are delegated to a single Slf4J logger instance.
* The log messages can be formatted by customizer.
*/
public class SingleSlf4JService implements ExtendedLogService, ExtendedLogReaderService {
private final org.slf4j.Logger delegate;
private final Map logLevel2methods;
private final Set listener;
private final BiFunction messageCustomizer;
/** Create facade for named logger with customized messages. */
public SingleSlf4JService(String name, BiFunction messageCustomizer) {
delegate = org.slf4j.LoggerFactory.getLogger(name);
logLevel2methods = new HashMap();
/*
* Audit message are treated as normal info-messages and might not get logged.
* Logging of Eclipse messages in Spotless formatter is meant for debugging purposes and
* detection of erroneous usage/override of internal Eclipse methods.
* Hence the concept of Audit is not required.
*/
logLevel2methods.put(LogLevel.AUDIT,
create(() -> true, m -> delegate.info(m), (m, e) -> delegate.info(m, e)));
logLevel2methods.put(LogLevel.DEBUG,
create(() -> delegate.isDebugEnabled(), m -> delegate.debug(m), (m, e) -> delegate.debug(m, e)));
logLevel2methods.put(LogLevel.ERROR,
create(() -> delegate.isErrorEnabled(), m -> delegate.error(m), (m, e) -> delegate.error(m, e)));
logLevel2methods.put(LogLevel.INFO,
create(() -> delegate.isInfoEnabled(), m -> delegate.info(m), (m, e) -> delegate.info(m, e)));
logLevel2methods.put(LogLevel.TRACE,
create(() -> delegate.isTraceEnabled(), m -> delegate.trace(m), (m, e) -> delegate.trace(m, e)));
logLevel2methods.put(LogLevel.WARN,
create(() -> delegate.isWarnEnabled(), m -> delegate.warn(m), (m, e) -> delegate.warn(m, e)));
listener = new HashSet();
this.messageCustomizer = messageCustomizer;
}
@Override
@Deprecated
//Backward compatibility with Eclipse OSGI 3.12
public void log(int level, String message) {
log(this, level, message);
}
@Override
@Deprecated
//Backward compatibility with Eclipse OSGI 3.12
public void log(int level, String message, @Nullable Throwable exception) {
log(this, level, message, exception);
}
@SuppressWarnings("rawtypes")
@Override
@Deprecated
//Backward compatibility with Eclipse OSGI 3.12
public void log(ServiceReference sr, int level, String message) {
log(this, level, message);
}
@SuppressWarnings("rawtypes")
@Override
@Deprecated
//Backward compatibility with Eclipse OSGI 3.12
public void log(ServiceReference sr, int level, String message, Throwable exception) {
log(this, level, message, exception);
}
@Override
public void log(Object context, int level, String message) {
log(context, level, message, null);
}
@Override
public void log(Object context, int level, String message, @Nullable Throwable exception) {
LogLevel logLevel = convertDeprectatedOsgiLevel(level);
log(new SimpleLogEntry(logLevel, message, exception));
}
@Override
public boolean isLoggable(int level) {
LogLevel logLevel = convertDeprectatedOsgiLevel(level);
return logLevel2methods.get(logLevel).isEnabled();
}
@SuppressWarnings("deprecation") ////Backward compatibility with Eclipse OSGI 3.12
private static LogLevel convertDeprectatedOsgiLevel(int level) {
switch (level) {
case SingleSlf4JService.LOG_DEBUG:
return LogLevel.DEBUG;
case SingleSlf4JService.LOG_INFO:
return LogLevel.INFO;
case SingleSlf4JService.LOG_ERROR:
return LogLevel.ERROR;
case SingleSlf4JService.LOG_WARNING:
return LogLevel.WARN;
default:
return LogLevel.AUDIT;
}
}
@Override
public String getName() {
return delegate.getName();
}
@Override
public Logger getLogger(String loggerName) {
return this;
}
@Override
public Logger getLogger(Bundle bundle, String loggerName) {
return this;
}
@Override
public void addLogListener(LogListener listener) {
synchronized (this.listener) {
this.listener.add(listener);
}
}
@Override
public void removeLogListener(LogListener listener) {
synchronized (this.listener) {
this.listener.remove(listener);
}
}
private void log(LogEntry entry) {
synchronized (listener) {
listener.stream().forEach(l -> l.logged(entry));
}
String customMessage = messageCustomizer.apply(entry.getMessage(), entry.getLogLevel());
logLevel2methods.get(entry.getLogLevel()).log(customMessage, entry.getException());
}
@Override
@Deprecated
//Backward compatibility with Eclipse OSGI 3.12
public Enumeration getLog() {
return Collections.emptyEnumeration(); //We do not provide historical information
}
@Override
public void addLogListener(LogListener listener, LogFilter filter) {
addLogListener(listener); //Listener must filter if required
}
@Override
public org.osgi.service.log.Logger getLogger(Class> clazz) {
return this;
}
@Override
@Deprecated
public L getLogger(String name, Class loggerType) {
throw new UnsupportedOperationException("Logger factory for indifivaul types currently not supported.");
}
@Override
@Deprecated
public L getLogger(Class> clazz, Class loggerType) {
return getLogger(getName(), loggerType);
}
@Override
@Deprecated
public L getLogger(Bundle bundle, String name, Class loggerType) {
return getLogger(getName(), loggerType);
}
@Override
public boolean isTraceEnabled() {
return delegate.isTraceEnabled();
}
@Override
public void trace(String message) {
log(new SimpleLogEntry(LogLevel.TRACE, message));
}
@Override
public void trace(String format, Object arg) {
trace(String.format(format, arg));
}
@Override
public void trace(String format, Object arg1, Object arg2) {
trace(String.format(format, arg1, arg2));
}
@Override
public void trace(String format, Object... arguments) {
trace(String.format(format, arguments));
}
@Override
public void trace(LoggerConsumer consumer) throws E {
consumer.accept(this);
}
@Override
public boolean isDebugEnabled() {
return delegate.isDebugEnabled();
}
@Override
public void debug(String message) {
log(new SimpleLogEntry(LogLevel.DEBUG, message));
}
@Override
public void debug(String format, Object arg) {
debug(String.format(format, arg));
}
@Override
public void debug(String format, Object arg1, Object arg2) {
debug(String.format(format, arg1, arg2));
}
@Override
public void debug(String format, Object... arguments) {
debug(String.format(format, arguments));
}
@Override
public void debug(LoggerConsumer consumer) throws E {
consumer.accept(this);
}
@Override
public boolean isInfoEnabled() {
return delegate.isInfoEnabled();
}
@Override
public void info(String message) {
log(new SimpleLogEntry(LogLevel.INFO, message));
}
@Override
public void info(String format, Object arg) {
info(String.format(format, arg));
}
@Override
public void info(String format, Object arg1, Object arg2) {
info(String.format(format, arg1, arg2));
}
@Override
public void info(String format, Object... arguments) {
info(String.format(format, arguments));
}
@Override
public void info(LoggerConsumer consumer) throws E {
consumer.accept(this);
}
@Override
public boolean isWarnEnabled() {
return delegate.isWarnEnabled();
}
@Override
public void warn(String message) {
log(new SimpleLogEntry(LogLevel.WARN, message));
}
@Override
public void warn(String format, Object arg) {
warn(String.format(format, arg));
}
@Override
public void warn(String format, Object arg1, Object arg2) {
warn(String.format(format, arg1, arg2));
}
@Override
public void warn(String format, Object... arguments) {
warn(String.format(format, arguments));
}
@Override
public void warn(LoggerConsumer consumer) throws E {
consumer.accept(this);
}
@Override
public boolean isErrorEnabled() {
return delegate.isErrorEnabled();
}
@Override
public void error(String message) {
log(new SimpleLogEntry(LogLevel.ERROR, message));
}
@Override
public void error(String format, Object arg) {
error(String.format(format, arg));
}
@Override
public void error(String format, Object arg1, Object arg2) {
error(String.format(format, arg1, arg2));
}
@Override
public void error(String format, Object... arguments) {
error(String.format(format, arguments));
}
@Override
public void error(LoggerConsumer consumer) throws E {
consumer.accept(this);
}
@Override
public void audit(String message) {
log(new SimpleLogEntry(LogLevel.AUDIT, message));
}
@Override
public void audit(String format, Object arg) {
audit(String.format(format, arg));
}
@Override
public void audit(String format, Object arg1, Object arg2) {
audit(String.format(format, arg1, arg2));
}
@Override
public void audit(String format, Object... arguments) {
audit(String.format(format, arguments));
}
/** Internal wrapper for Eclipse OSGI 3.12 based logs and new log services. */
private static class SimpleLogEntry implements LogEntry {
private final LogLevel level;
private final String message;
private final Optional execption;
public SimpleLogEntry(LogLevel level, String message) {
this(level, message, Optional.empty());
}
public SimpleLogEntry(LogLevel level, String message, @Nullable Throwable execption) {
this(level, message, Optional.ofNullable(execption));
}
private SimpleLogEntry(LogLevel level, String message, Optional execption) {
this.level = level;
this.message = message;
this.execption = execption;
}
@Override
public Bundle getBundle() {
//Return the spotless framework bundle
return InternalPlatform.getDefault().getBundleContext().getBundle();
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public ServiceReference getServiceReference() {
return null;
}
@Override
@Deprecated
//Backward compatibility with Eclipse OSGI 3.12
public int getLevel() {
switch (level) {
case DEBUG:
case TRACE:
return SingleSlf4JService.LOG_DEBUG;
case AUDIT:
case INFO:
return SingleSlf4JService.LOG_INFO;
case ERROR:
return SingleSlf4JService.LOG_ERROR;
case WARN:
return SingleSlf4JService.LOG_WARNING;
}
return SingleSlf4JService.LOG_ERROR; //Don't fail here. Just log it as error. This is anyway just for debugging internal problems.
}
@Override
public String getMessage() {
return message;
}
@Override
public Throwable getException() {
return execption.orElse(null);
}
@Override
public long getTime() {
return 0;
}
@Override
public String toString() {
StringWriter result = new StringWriter();
result.write(message);
if (execption.isPresent()) {
result.write('\n');
result.write(execption.get().toString());
result.write('\n');
execption.get().printStackTrace(new PrintWriter(result));
}
return result.toString();
}
@Override
public LogLevel getLogLevel() {
return level;
}
@Override
public String getLoggerName() {
return this.getClass().getSimpleName();
}
@Override
public long getSequence() {
return 0;
}
@Override
public String getThreadInfo() {
return null;
}
@Override
public StackTraceElement getLocation() {
return null; // Not used by SingleSlf4JService
}
}
private static LogMethods create(Supplier enabled, Consumer log, BiConsumer logException) {
return new LogMethods(enabled, log, logException);
}
private static class LogMethods {
private final Supplier enabled;
private final Consumer log;
private final BiConsumer logException;
private LogMethods(Supplier enabled, Consumer log, BiConsumer logException) {
this.enabled = enabled;
this.log = log;
this.logException = logException;
}
public boolean isEnabled() {
return enabled.get();
}
public void log(String message) {
log.accept(message);
}
public void log(String message, @Nullable Throwable exception) {
if (null == exception) {
log(message);
} else {
logException.accept(message, exception);
}
}
};
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy