001    package org.apache.fulcrum.yaafi.framework.tls;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.HashMap;
023    import java.util.Map;
024    
025    /**
026     * Implementation of {@link org.apache.fulcrum.yaafi.framework.tls.ThreadLocalStorage}.
027     *
028     * The code was pasted from the Hivemnind container written by
029     * Howard Lewis Ship and Harish Krishnaswamy
030     *
031     * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
032     */
033    
034    public class ThreadLocalStorageImpl implements ThreadLocalStorage
035    {
036        private static final String INITIALIZED_KEY =
037            "$org.apache.fulcrum.yaafi.framework.tls.ThreadLocalStorageImpl#initialized$";
038    
039        private CleanableThreadLocal local = new CleanableThreadLocal();
040    
041        private static class CleanableThreadLocal extends ThreadLocal
042        {
043            /**
044             * <p>
045             * Intializes the variable with a HashMap containing a single Boolean flag to denote the
046             * initialization of the variable.
047             */
048            protected Object initialValue()
049            {
050                // NOTE: This is a workaround to circumvent the ThreadLocal behavior.
051                // It would be easier if the implementation of ThreadLocal.get() checked for
052                // the existence of the thread local map, after initialValue() is evaluated,
053                // and used it instead of creating a new map always after initialization (possibly
054                // overwriting any variables created from within ThreadLocal.initialValue()).
055    
056                Map map = new HashMap();
057                map.put(INITIALIZED_KEY, Boolean.TRUE);
058    
059                return map;
060            }
061        }
062    
063        /**
064         * Gets the thread local variable and registers the listener with ThreadEventNotifier
065         * if the thread local variable has been initialized. The registration cannot be done from
066         * within {@link CleanableThreadLocal#initialValue()} because the notifier's thread local
067         * variable will be overwritten and the listeners for the thread will be lost.
068         */
069        private Map getThreadLocalVariable()
070        {
071            Map map = (Map) local.get();
072            return map;
073        }
074    
075        public Object get(String key)
076        {
077            Map map = getThreadLocalVariable();
078    
079            return map.get(key);
080        }
081    
082        public void put(String key, Object value)
083        {
084            Map map = getThreadLocalVariable();
085    
086            map.put(key, value);
087        }
088    
089        public boolean containsKey(String key)
090        {
091            Map map = getThreadLocalVariable();
092    
093            return map.containsKey(key);
094        }
095    
096        public void clear()
097        {
098            Map map = (Map) local.get();
099    
100            if (map != null)
101            {
102                map.clear();
103            }
104        }
105    }