001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.logging.slf4j;
018
019import java.util.Map;
020import java.util.Map.Entry;
021
022import org.apache.logging.log4j.spi.CleanableThreadContextMap;
023import org.apache.logging.log4j.util.SortedArrayStringMap;
024import org.apache.logging.log4j.util.StringMap;
025import org.slf4j.MDC;
026
027/**
028 * Bind the ThreadContextMap to the SLF4J MDC.
029 */
030public class MDCContextMap implements CleanableThreadContextMap {
031
032    private static final StringMap EMPTY_CONTEXT_DATA = new SortedArrayStringMap(1);
033    static {
034        EMPTY_CONTEXT_DATA.freeze();
035    }
036
037    @Override
038    public void put(final String key, final String value) {
039        MDC.put(key, value);
040    }
041
042    @Override
043    public void putAll(final Map<String, String> m) {
044        for (final Entry<String, String> entry : m.entrySet()) {
045            MDC.put(entry.getKey(), entry.getValue());
046        }
047    }
048
049    @Override
050    public String get(final String key) {
051        return MDC.get(key);
052    }
053
054    @Override
055    public void remove(final String key) {
056        MDC.remove(key);
057    }
058
059
060    @Override
061    public void removeAll(final Iterable<String> keys) {
062        for (final String key : keys) {
063            MDC.remove(key);
064        }
065    }
066
067    @Override
068    public void clear() {
069        MDC.clear();
070    }
071
072    @Override
073    public boolean containsKey(final String key) {
074        return MDC.getCopyOfContextMap().containsKey(key);
075    }
076
077    @Override
078    @SuppressWarnings("unchecked") // nothing we can do about this, restricted by SLF4J API
079    public Map<String, String> getCopy() {
080        return MDC.getCopyOfContextMap();
081    }
082
083    @Override
084    @SuppressWarnings("unchecked") // nothing we can do about this, restricted by SLF4J API
085    public Map<String, String> getImmutableMapOrNull() {
086        return MDC.getCopyOfContextMap();
087    }
088
089    @Override
090    public boolean isEmpty() {
091        return MDC.getCopyOfContextMap().isEmpty();
092    }
093
094    @Override
095    public StringMap getReadOnlyContextData() {
096        final Map<String, String> copy = getCopy();
097        if (copy.isEmpty()) {
098            return EMPTY_CONTEXT_DATA;
099        }
100        final StringMap result = new SortedArrayStringMap();
101        for (final Entry<String, String> entry : copy.entrySet()) {
102            result.putValue(entry.getKey(), entry.getValue());
103        }
104        return result;
105    }
106}