/**
  * Bind the given resource for the given key to the current thread.
  *
  * @param key the key to bind the value to (usually the resource factory)
  * @param value the value to bind (usually the active resource object)
  * @throws IllegalStateException if there is already a value bound to the thread
  * @see ResourceTransactionManager#getResourceFactory()
  */
 public static void bindResource(Object key, Object value) throws IllegalStateException {
   Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
   Assert.notNull(value, "Value must not be null");
   Map<Object, Object> map = resources.get();
   // set ThreadLocal Map if none found
   if (map == null) {
     map = new HashMap<Object, Object>();
     resources.set(map);
   }
   if (map.put(actualKey, value) != null) {
     throw new IllegalStateException(
         "Already value ["
             + map.get(actualKey)
             + "] for key ["
             + actualKey
             + "] bound to thread ["
             + Thread.currentThread().getName()
             + "]");
   }
   if (logger.isTraceEnabled()) {
     logger.trace(
         "Bound value ["
             + value
             + "] for key ["
             + actualKey
             + "] to thread ["
             + Thread.currentThread().getName()
             + "]");
   }
 }
 /**
  * Unbind a resource for the given key from the current thread.
  *
  * @param key the key to unbind (usually the resource factory)
  * @return the previously bound value (usually the active resource object)
  * @throws IllegalStateException if there is no value bound to the thread
  * @see ResourceTransactionManager#getResourceFactory()
  */
 public static Object unbindResource(Object key) throws IllegalStateException {
   Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
   Object value = doUnbindResource(actualKey);
   if (value == null) {
     throw new IllegalStateException(
         "No value for key ["
             + actualKey
             + "] bound to thread ["
             + Thread.currentThread().getName()
             + "]");
   }
   return value;
 }
 /**
  * Retrieve a resource for the given key that is bound to the current thread.
  *
  * @param key the key to check (usually the resource factory)
  * @return a value bound to the current thread (usually the active resource object), or <code>null
  *     </code> if none
  * @see ResourceTransactionManager#getResourceFactory()
  */
 public static Object getResource(Object key) {
   Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
   Object value = doGetResource(actualKey);
   if (value != null && logger.isTraceEnabled()) {
     logger.trace(
         "Retrieved value ["
             + value
             + "] for key ["
             + actualKey
             + "] bound to thread ["
             + Thread.currentThread().getName()
             + "]");
   }
   return value;
 }
 /**
  * Unbind a resource for the given key from the current thread.
  *
  * @param key the key to unbind (usually the resource factory)
  * @return the previously bound value, or <code>null</code> if none bound
  */
 public static Object unbindResourceIfPossible(Object key) {
   Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
   return doUnbindResource(actualKey);
 }
 /**
  * Check if there is a resource for the given key bound to the current thread.
  *
  * @param key the key to check (usually the resource factory)
  * @return if there is a value bound to the current thread
  * @see ResourceTransactionManager#getResourceFactory()
  */
 public static boolean hasResource(Object key) {
   Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
   Object value = doGetResource(actualKey);
   return (value != null);
 }