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     */
017    
018    package org.apache.geronimo.system.logging.log4j;
019    
020    import java.util.HashMap;
021    import java.util.LinkedList;
022    import java.util.Map;
023    
024    /**
025     * Provides named nested diagnotic contexts.
026     *
027     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
028     */
029    public final class NamedNDC {
030        /**
031         * Mapping from names to NamedNDCs.
032         * Currently there is no way to remove a NamedNCD once created, so be sure you really
033         * want a new NDC before creating one.
034         * @todo make this a weak-valued map
035         */
036        private static final Map contexts = new HashMap();
037    
038        /**
039         * Gets the NamedNDC by name, or creates a new one of one does not already exist.
040         * @param name the name of the desired NamedNDC
041         * @return the existing NamedNDC or a new one
042         */
043        public static NamedNDC getNamedNDC(String name) {
044            synchronized (contexts) {
045                NamedNDC context = (NamedNDC) contexts.get(name);
046                if (context == null) {
047                    context = new NamedNDC();
048                    contexts.put(name, context);
049                }
050                return context;
051            }
052        }
053    
054        private final ListThreadLocal listThreadLocal = new ListThreadLocal();
055    
056        private NamedNDC() {
057        }
058    
059        public void push(Object value) {
060            listThreadLocal.getList().addLast(value);
061        }
062    
063        public Object get() {
064            LinkedList list = listThreadLocal.getList();
065            if (list.isEmpty()) {
066                return null;
067            }
068            return list.getLast();
069        }
070    
071        public Object pop() {
072            LinkedList list = listThreadLocal.getList();
073            if (list.isEmpty()) {
074                return null;
075            }
076            return list.removeLast();
077        }
078    
079        public void clear() {
080            listThreadLocal.getList().clear();
081        }
082    
083        private final static class ListThreadLocal extends ThreadLocal {
084            public LinkedList getList() {
085                return (LinkedList) get();
086            }
087    
088            protected Object initialValue() {
089                return new LinkedList();
090            }
091        }
092    }