001
014
015 package com.liferay.portal.kernel.util;
016
017 import com.liferay.portal.kernel.memory.EqualityWeakReference;
018
019 import java.lang.ref.Reference;
020 import java.lang.ref.ReferenceQueue;
021 import java.lang.ref.WeakReference;
022 import java.lang.reflect.Constructor;
023 import java.lang.reflect.Field;
024 import java.lang.reflect.InvocationHandler;
025 import java.lang.reflect.Proxy;
026
027 import java.util.concurrent.ConcurrentHashMap;
028 import java.util.concurrent.ConcurrentMap;
029
030
033 public class ProxyUtil {
034
035 public static InvocationHandler getInvocationHandler(Object proxy) {
036 if (!isProxyClass(proxy.getClass())) {
037 throw new IllegalArgumentException("Not a proxy instance");
038 }
039
040 try {
041 return (InvocationHandler)_invocationHandlerField.get(proxy);
042 }
043 catch (Exception e) {
044 throw new IllegalArgumentException(e);
045 }
046 }
047
048 public static Class<?> getProxyClass(
049 ClassLoader classLoader, Class<?>... interfaceClasses) {
050
051 EqualityWeakReference<ClassLoader> classLoaderReference =
052 new EqualityWeakReference<ClassLoader>(classLoader);
053
054 ConcurrentMap<LookupKey, Reference<Class<?>>> classReferences =
055 _classReferences.get(classLoaderReference);
056
057 if (classReferences == null) {
058 classReferences =
059 new ConcurrentHashMap<LookupKey, Reference<Class<?>>>();
060
061 classLoaderReference = new EqualityWeakReference<ClassLoader>(
062 classLoader, _classLoaderReferenceQueue);
063
064 ConcurrentMap<LookupKey, Reference<Class<?>>> oldClassReferences =
065 _classReferences.putIfAbsent(
066 classLoaderReference, classReferences);
067
068 if (oldClassReferences != null) {
069 classReferences = oldClassReferences;
070
071 classLoaderReference.enqueue();
072 }
073 }
074
075 LookupKey lookupKey = new LookupKey(interfaceClasses);
076
077 Reference<Class<?>> classReference = classReferences.get(lookupKey);
078
079 Class<?> clazz = null;
080
081 if ((classReference == null) ||
082 ((clazz = classReference.get()) == null)) {
083
084 synchronized(classReferences) {
085 classReference = classReferences.get(lookupKey);
086
087 if ((classReference == null) ||
088 ((clazz = classReference.get()) == null)) {
089
090 clazz = Proxy.getProxyClass(classLoader, interfaceClasses);
091
092 classReferences.put(
093 lookupKey, new WeakReference<Class<?>>(clazz));
094 }
095 }
096 }
097
098 Constructor<?> constructor = null;
099
100 try {
101 constructor = clazz.getConstructor(_argumentsClazz);
102 }
103 catch (Exception e) {
104 throw new InternalError(e.toString());
105 }
106
107 EqualityWeakReference<Class<?>> proxyClassReference =
108 new EqualityWeakReference<Class<?>>(
109 clazz, _proxyClassReferenceQueue);
110
111 _constructors.putIfAbsent(proxyClassReference, constructor);
112
113 while (true) {
114 EqualityWeakReference<ClassLoader> staleClassLoaderReference =
115 (EqualityWeakReference<ClassLoader>)
116 _classLoaderReferenceQueue.poll();
117
118 if (staleClassLoaderReference == null) {
119 break;
120 }
121
122 _classReferences.remove(staleClassLoaderReference);
123 }
124
125 while (true) {
126 EqualityWeakReference<Class<?>> staleProxyClassReference =
127 (EqualityWeakReference<Class<?>>)
128 _proxyClassReferenceQueue.poll();
129
130 if (staleProxyClassReference == null) {
131 break;
132 }
133
134 _constructors.remove(staleProxyClassReference);
135 }
136
137 return clazz;
138 }
139
140 public static boolean isProxyClass(Class<?> clazz) {
141 if (clazz == null) {
142 throw new NullPointerException();
143 }
144
145 EqualityWeakReference<Class<?>> equalityWeakReference =
146 new EqualityWeakReference<Class<?>>(clazz);
147
148 return _constructors.containsKey(equalityWeakReference);
149 }
150
151 public static Object newProxyInstance(
152 ClassLoader classLoader, Class<?>[] interfaces,
153 InvocationHandler invocationHandler) {
154
155 Class<?> clazz = getProxyClass(classLoader, interfaces);
156
157 EqualityWeakReference<Class<?>> proxyClassReference =
158 new EqualityWeakReference<Class<?>>(clazz);
159
160 Constructor<?> constructor = _constructors.get(proxyClassReference);
161
162 try {
163 return constructor.newInstance(new Object[] {invocationHandler});
164 }
165 catch (Exception e) {
166 throw new InternalError(e.toString());
167 }
168 }
169
170 private static Class<?>[] _argumentsClazz = {InvocationHandler.class};
171 private static ReferenceQueue<ClassLoader> _classLoaderReferenceQueue =
172 new ReferenceQueue<ClassLoader>();
173 private static ConcurrentMap
174 <EqualityWeakReference<ClassLoader>,
175 ConcurrentMap<LookupKey, Reference<Class<?>>>> _classReferences =
176 new ConcurrentHashMap<EqualityWeakReference<ClassLoader>,
177 ConcurrentMap<LookupKey, Reference<Class<?>>>>();
178 private static ConcurrentMap
179 <EqualityWeakReference<Class<?>>, Constructor<?>> _constructors =
180 new ConcurrentHashMap
181 <EqualityWeakReference<Class<?>>, Constructor<?>>();
182 private static Field _invocationHandlerField;
183 private static ReferenceQueue<Class<?>> _proxyClassReferenceQueue =
184 new ReferenceQueue<Class<?>>();
185
186 private static class LookupKey {
187
188 public LookupKey(Class<?>[] interfaces) {
189 _interfaces = interfaces;
190
191 _hashCode = 1;
192
193 for (Class<?> clazz : interfaces) {
194 String name = clazz.getName();
195
196 _hashCode = HashUtil.hash(_hashCode, name.hashCode());
197 }
198 }
199
200 @Override
201 public boolean equals(Object obj) {
202 LookupKey lookupKey = (LookupKey)obj;
203
204 if (_interfaces.length != lookupKey._interfaces.length) {
205 return false;
206 }
207
208 for (int i = 0; i < _interfaces.length; i++) {
209 if (_interfaces[i] != lookupKey._interfaces[i]) {
210 return false;
211 }
212 }
213
214 return true;
215 }
216
217 @Override
218 public int hashCode() {
219 return _hashCode;
220 }
221
222 private int _hashCode;
223 private final Class<?>[] _interfaces;
224
225 }
226
227 static {
228 try {
229 _invocationHandlerField = ReflectionUtil.getDeclaredField(
230 Proxy.class, "h");
231 }
232 catch (Exception e) {
233 throw new ExceptionInInitializerError(e);
234 }
235 }
236
237 }