001
014
015 package com.liferay.portal.kernel.util;
016
017 import com.liferay.portal.kernel.concurrent.ConcurrentReferenceKeyHashMap;
018 import com.liferay.portal.kernel.concurrent.ConcurrentReferenceValueHashMap;
019 import com.liferay.portal.kernel.memory.FinalizeManager;
020
021 import java.lang.reflect.Constructor;
022 import java.lang.reflect.Field;
023 import java.lang.reflect.InvocationHandler;
024 import java.lang.reflect.Proxy;
025
026 import java.util.concurrent.ConcurrentMap;
027
028
031 public class ProxyUtil {
032
033 public static InvocationHandler getInvocationHandler(Object proxy) {
034 if (!isProxyClass(proxy.getClass())) {
035 throw new IllegalArgumentException("Not a proxy instance");
036 }
037
038 try {
039 return (InvocationHandler)_invocationHandlerField.get(proxy);
040 }
041 catch (Exception e) {
042 throw new IllegalArgumentException(e);
043 }
044 }
045
046 public static Class<?> getProxyClass(
047 ClassLoader classLoader, Class<?>... interfaceClasses) {
048
049 ConcurrentMap<LookupKey, Class<?>> classReferences =
050 _classReferences.get(classLoader);
051
052 if (classReferences == null) {
053 classReferences = new ConcurrentReferenceValueHashMap<>(
054 FinalizeManager.WEAK_REFERENCE_FACTORY);
055
056 ConcurrentMap<LookupKey, Class<?>> oldClassReferences =
057 _classReferences.putIfAbsent(classLoader, classReferences);
058
059 if (oldClassReferences != null) {
060 classReferences = oldClassReferences;
061 }
062 }
063
064 LookupKey lookupKey = new LookupKey(interfaceClasses);
065
066 Class<?> clazz = classReferences.get(lookupKey);
067
068 if (clazz == null) {
069 synchronized(classReferences) {
070 clazz = classReferences.get(lookupKey);
071
072 if (clazz == null) {
073 clazz = Proxy.getProxyClass(classLoader, interfaceClasses);
074
075 classReferences.put(lookupKey, clazz);
076 }
077 }
078 }
079
080 Constructor<?> constructor = null;
081
082 try {
083 constructor = clazz.getConstructor(_argumentsClazz);
084
085 constructor.setAccessible(true);
086 }
087 catch (Exception e) {
088 throw new InternalError(e.toString());
089 }
090
091 _constructors.putIfAbsent(clazz, constructor);
092
093 return clazz;
094 }
095
096 public static boolean isProxyClass(Class<?> clazz) {
097 if (clazz == null) {
098 throw new NullPointerException();
099 }
100
101 return _constructors.containsKey(clazz);
102 }
103
104 public static Object newProxyInstance(
105 ClassLoader classLoader, Class<?>[] interfaces,
106 InvocationHandler invocationHandler) {
107
108 Constructor<?> constructor = _constructors.get(
109 getProxyClass(classLoader, interfaces));
110
111 try {
112 return constructor.newInstance(new Object[] {invocationHandler});
113 }
114 catch (Exception e) {
115 throw new InternalError(e.toString());
116 }
117 }
118
119 private static final Class<?>[] _argumentsClazz = {InvocationHandler.class};
120 private static final ConcurrentMap
121 <ClassLoader, ConcurrentMap<LookupKey, Class<?>>> _classReferences =
122 new ConcurrentReferenceKeyHashMap<>(
123 FinalizeManager.WEAK_REFERENCE_FACTORY);
124 private static final ConcurrentMap<Class<?>, Constructor<?>> _constructors =
125 new ConcurrentReferenceKeyHashMap<>(
126 new ConcurrentReferenceValueHashMap<Class<?>, Constructor<?>>(
127 FinalizeManager.WEAK_REFERENCE_FACTORY),
128 FinalizeManager.WEAK_REFERENCE_FACTORY);
129 private static final Field _invocationHandlerField;
130
131 static {
132 try {
133 _invocationHandlerField = ReflectionUtil.getDeclaredField(
134 Proxy.class, "h");
135 }
136 catch (Exception e) {
137 throw new ExceptionInInitializerError(e);
138 }
139 }
140
141 private static class LookupKey {
142
143 public LookupKey(Class<?>[] interfaces) {
144 _interfaces = interfaces;
145
146 int hashCode = 0;
147
148 for (Class<?> clazz : interfaces) {
149 hashCode = HashUtil.hash(hashCode, clazz.getName());
150 }
151
152 _hashCode = hashCode;
153 }
154
155 @Override
156 public boolean equals(Object obj) {
157 LookupKey lookupKey = (LookupKey)obj;
158
159 if (_interfaces.length != lookupKey._interfaces.length) {
160 return false;
161 }
162
163 for (int i = 0; i < _interfaces.length; i++) {
164 if (_interfaces[i] != lookupKey._interfaces[i]) {
165 return false;
166 }
167 }
168
169 return true;
170 }
171
172 @Override
173 public int hashCode() {
174 return _hashCode;
175 }
176
177 private final int _hashCode;
178 private final Class<?>[] _interfaces;
179
180 }
181
182 }