Clover coverage report - Code Coverage for hivemind release 1.1-beta-3
Coverage timestamp: Mon Aug 22 2005 21:38:15 EDT
file stats: LOC: 119   Methods: 7
NCLOC: 56   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
ThreadLocalStorageImpl.java 75% 100% 100% 96.4%
coverage coverage
 1    // Copyright 2004, 2005 The Apache Software Foundation
 2    //
 3    // Licensed under the Apache License, Version 2.0 (the "License");
 4    // you may not use this file except in compliance with the License.
 5    // You may obtain a copy of the License at
 6    //
 7    // http://www.apache.org/licenses/LICENSE-2.0
 8    //
 9    // Unless required by applicable law or agreed to in writing, software
 10    // distributed under the License is distributed on an "AS IS" BASIS,
 11    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    // See the License for the specific language governing permissions and
 13    // limitations under the License.
 14   
 15    package org.apache.hivemind.service.impl;
 16   
 17    import java.util.HashMap;
 18    import java.util.Map;
 19   
 20    import org.apache.hivemind.service.ThreadCleanupListener;
 21    import org.apache.hivemind.service.ThreadEventNotifier;
 22    import org.apache.hivemind.service.ThreadLocalStorage;
 23   
 24    /**
 25    * Implementation of {@link org.apache.hivemind.service.ThreadLocalStorage}.
 26    *
 27    * @author Howard Lewis Ship, Harish Krishnaswamy
 28    */
 29    public class ThreadLocalStorageImpl implements ThreadLocalStorage, ThreadCleanupListener
 30    {
 31    private static final String INITIALIZED_KEY =
 32    "$org.apache.hivemind.service.impl.ThreadLocalStorageImpl#initialized$";
 33   
 34    private CleanableThreadLocal _local = new CleanableThreadLocal();
 35    private ThreadEventNotifier _notifier;
 36   
 37    private static class CleanableThreadLocal extends ThreadLocal
 38    {
 39    /**
 40    * <p>
 41    * Intializes the variable with a HashMap containing a single Boolean flag to denote the
 42    * initialization of the variable. The Boolean flag will be used to determine when to
 43    * register the listener with {@link ThreadEventNotifier}.
 44    * <p>
 45    * The registration cannot be done from here because it may get lost once the caller method (
 46    * {@link ThreadLocal#get()}or {@link ThreadLocal#set(java.lang.Object)} completes, if
 47    * this was the first ThreadLocal variable access for the Thread.
 48    */
 49  87 protected Object initialValue()
 50    {
 51    // NOTE: This is a workaround to circumvent the ThreadLocal behavior.
 52    // It would be easier if the implementation of ThreadLocal.get() checked for
 53    // the existence of the thread local map, after initialValue() is evaluated,
 54    // and used it instead of creating a new map always after initialization (possibly
 55    // overwriting any variables created from within ThreadLocal.initialValue()).
 56   
 57  87 Map map = new HashMap();
 58  87 map.put(INITIALIZED_KEY, Boolean.TRUE);
 59   
 60  87 return map;
 61    }
 62    }
 63   
 64    /**
 65    * Gets the thread local variable and registers the listener with {@link ThreadEventNotifier}
 66    * if the thread local variable has been initialized. The registration cannot be done from
 67    * within {@link CleanableThreadLocal#initialValue()} because the notifier's thread local
 68    * variable will be overwritten and the listeners for the thread will be lost.
 69    */
 70  817 private Map getThreadLocalVariable()
 71    {
 72  817 Map map = (Map) _local.get();
 73   
 74  817 if (Boolean.TRUE.equals(map.get(INITIALIZED_KEY)) && _notifier != null)
 75    {
 76  83 _notifier.addThreadCleanupListener(this);
 77   
 78  83 map.remove(INITIALIZED_KEY);
 79    }
 80   
 81  817 return map;
 82    }
 83   
 84  11 public Object get(String key)
 85    {
 86  11 Map map = getThreadLocalVariable();
 87   
 88  11 return map.get(key);
 89    }
 90   
 91  806 public void put(String key, Object value)
 92    {
 93  806 Map map = getThreadLocalVariable();
 94   
 95  806 map.put(key, value);
 96    }
 97   
 98  805 public void clear()
 99    {
 100  805 Map map = (Map) _local.get();
 101   
 102  805 if (map != null)
 103  805 map.clear();
 104    }
 105   
 106  6 public void setNotifier(ThreadEventNotifier notifier)
 107    {
 108  6 _notifier = notifier;
 109    }
 110   
 111    /**
 112    * Invokes {@link #clear()}.
 113    */
 114  803 public void threadDidCleanup()
 115    {
 116  803 clear();
 117    }
 118   
 119    }