001
014
015 package com.liferay.portal.spring.hibernate;
016
017 import com.liferay.portal.kernel.util.CentralizedThreadLocal;
018 import com.liferay.portal.kernel.util.InitialThreadLocal;
019 import com.liferay.portal.kernel.util.ReflectionUtil;
020
021 import java.lang.reflect.Field;
022 import java.lang.reflect.Modifier;
023
024 import java.util.HashMap;
025 import java.util.Map;
026
027 import org.springframework.core.NamedThreadLocal;
028 import org.springframework.transaction.support.ResourceHolder;
029 import org.springframework.transaction.support.TransactionSynchronizationManager;
030
031
034 public class SpringHibernateThreadLocalUtil {
035
036 public static <T> T getResource(Object key) {
037 Map<Object, Object> resources = _resourcesThreadLocal.get();
038
039 if (resources == null) {
040 return null;
041 }
042
043 Object resource = resources.get(key);
044
045 if (resource instanceof ResourceHolder) {
046 ResourceHolder resourceHolder = (ResourceHolder)resource;
047
048 if (resourceHolder.isVoid()) {
049 resources.remove(key);
050
051 if (resources.isEmpty()) {
052 _resourcesThreadLocal.remove();
053 }
054
055 return null;
056 }
057 }
058
059 return (T)resource;
060 }
061
062 public static <T> T setResource(Object key, Object resource) {
063 Map<Object, Object> resources = _resourcesThreadLocal.get();
064
065 Object oldResource = null;
066
067 if (resource == null) {
068 if (resources == null) {
069 return null;
070 }
071
072 oldResource = resources.remove(key);
073
074 if (resources.isEmpty()) {
075 _resourcesThreadLocal.remove();
076 }
077 }
078 else {
079 if (resources == null) {
080 resources = new HashMap<Object, Object>();
081
082 _resourcesThreadLocal.set(resources);
083 }
084
085 oldResource = resources.put(key, resource);
086 }
087
088 if (oldResource instanceof ResourceHolder) {
089 ResourceHolder resourceHolder = (ResourceHolder)oldResource;
090
091 if (resourceHolder.isVoid()) {
092 oldResource = null;
093 }
094 }
095
096 return (T)oldResource;
097 }
098
099 private static final ThreadLocal<Map<Object, Object>> _resourcesThreadLocal;
100
101 static {
102 try {
103 Field nameField = ReflectionUtil.getDeclaredField(
104 NamedThreadLocal.class, "name");
105
106 ThreadLocal<?> resourcesThreadLocal = null;
107
108 for (Field field : ReflectionUtil.getDeclaredFields(
109 TransactionSynchronizationManager.class)) {
110
111 if (Modifier.isStatic(field.getModifiers()) &&
112 ThreadLocal.class.isAssignableFrom(field.getType())) {
113
114 ThreadLocal<Object> threadLocal =
115 (ThreadLocal<Object>)field.get(null);
116
117 Object value = threadLocal.get();
118
119 if (threadLocal instanceof NamedThreadLocal) {
120 threadLocal = new InitialThreadLocal<Object>(
121 (String)nameField.get(threadLocal), null);
122 }
123 else {
124 threadLocal = new CentralizedThreadLocal<Object>(false);
125 }
126
127 if (value != null) {
128 threadLocal.set(value);
129 }
130
131 field.set(null, threadLocal);
132
133 String name = field.getName();
134
135 if (name.equals("resources")) {
136 resourcesThreadLocal = threadLocal;
137 }
138 }
139 }
140
141 if (resourcesThreadLocal == null) {
142 throw new ExceptionInInitializerError(
143 "Unable to locate \"resources\" thread local field from " +
144 TransactionSynchronizationManager.class);
145 }
146
147 _resourcesThreadLocal =
148 (ThreadLocal<Map<Object, Object>>)resourcesThreadLocal;
149 }
150 catch (Exception e) {
151 throw new ExceptionInInitializerError(e);
152 }
153 }
154
155 }