blob: 9aa03a6b761856602d6d8fe4cb7f241089386093 [file]
/*
* 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.logging.admin.internal;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.WeakHashMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.logging.admin.LoggingAdmin;
import org.jspecify.annotations.Nullable;
import org.slf4j.LoggerFactory;
class LogbackAdmin implements LoggingAdmin {
private static final ReentrantLock lock = new ReentrantLock();
private static final Map<LoggerContext, Object> tokensByLoggerContext = new WeakHashMap<>();
private static final List<String> levels = Collections.unmodifiableList(
Stream.of(Level.OFF, Level.ERROR, Level.WARN, Level.INFO, Level.DEBUG, Level.TRACE)
.map(Level::toString)
.collect(Collectors.toList()));
private final LoggerContext loggerContext;
LogbackAdmin(final LoggerContext loggerContext) {
this.loggerContext = loggerContext;
}
@Override
public List<String> getSupportedLevels() {
return levels;
}
@Override
public Map<String, @Nullable String> getLevels() {
Map<String, @Nullable String> loggerLevels = new HashMap<>();
loggerContext
.getLoggerList()
.forEach(logger -> loggerLevels.put(rootToEmpty(logger.getName()), getLevel(logger)));
return loggerLevels;
}
@Override
public @Nullable String getLevel(String loggerName) {
return getLevel(loggerContext.getLogger(emptyToRoot(loggerName)));
}
private static @Nullable String getLevel(Logger logger) {
return Optional.ofNullable(logger.getLevel()).map(Level::toString).orElse(null);
}
@Override
public void setLevel(String loggerName, @Nullable String level) {
loggerContext.getLogger(emptyToRoot(loggerName)).setLevel(level != null ? Level.valueOf(level) : null);
}
private String rootToEmpty(String loggerName) {
return Logger.ROOT_LOGGER_NAME.equals(loggerName) ? "" : loggerName;
}
private String emptyToRoot(String loggerName) {
return loggerName.isEmpty() ? Logger.ROOT_LOGGER_NAME : loggerName;
}
static boolean isActive() {
return LoggerFactory.getILoggerFactory() instanceof ch.qos.logback.classic.LoggerContext;
}
static LoggingAdmin newInstance(Object token) {
lock.lock();
try {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
if (tokensByLoggerContext.computeIfAbsent(loggerContext, k -> token) != token) {
throw new SecurityException("The security token does not match: " + token);
}
return new LogbackAdmin(loggerContext);
} finally {
lock.unlock();
}
}
}