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        Map<String, String> map = MDC.getCopyOfContextMap();
075        return map != null && map.containsKey(key);
076    }
077
078    @Override
079    @SuppressWarnings("unchecked") // nothing we can do about this, restricted by SLF4J API
080    public Map<String, String> getCopy() {
081        return MDC.getCopyOfContextMap();
082    }
083
084    @Override
085    @SuppressWarnings("unchecked") // nothing we can do about this, restricted by SLF4J API
086    public Map<String, String> getImmutableMapOrNull() {
087        return MDC.getCopyOfContextMap();
088    }
089
090    @Override
091    public boolean isEmpty() {
092        Map<String, String> map = MDC.getCopyOfContextMap();
093        return map == null || map.isEmpty();
094    }
095
096    @Override
097    public StringMap getReadOnlyContextData() {
098        final Map<String, String> copy = getCopy();
099        if (copy.isEmpty()) {
100            return EMPTY_CONTEXT_DATA;
101        }
102        final StringMap result = new SortedArrayStringMap();
103        for (final Entry<String, String> entry : copy.entrySet()) {
104            result.putValue(entry.getKey(), entry.getValue());
105        }
106        return result;
107    }
108}