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 =
054 new ConcurrentReferenceValueHashMap<LookupKey, Class<?>>(
055 FinalizeManager.WEAK_REFERENCE_FACTORY);
056
057 ConcurrentMap<LookupKey, Class<?>> oldClassReferences =
058 _classReferences.putIfAbsent(classLoader, classReferences);
059
060 if (oldClassReferences != null) {
061 classReferences = oldClassReferences;
062 }
063 }
064
065 LookupKey lookupKey = new LookupKey(interfaceClasses);
066
067 Class<?> clazz = classReferences.get(lookupKey);
068
069 if (clazz == null) {
070 synchronized(classReferences) {
071 clazz = classReferences.get(lookupKey);
072
073 if (clazz == null) {
074 clazz = Proxy.getProxyClass(classLoader, interfaceClasses);
075
076 classReferences.put(lookupKey, clazz);
077 }
078 }
079 }
080
081 Constructor<?> constructor = null;
082
083 try {
084 constructor = clazz.getConstructor(_argumentsClazz);
085
086 constructor.setAccessible(true);
087 }
088 catch (Exception e) {
089 throw new InternalError(e.toString());
090 }
091
092 _constructors.putIfAbsent(clazz, constructor);
093
094 return clazz;
095 }
096
097 public static boolean isProxyClass(Class<?> clazz) {
098 if (clazz == null) {
099 throw new NullPointerException();
100 }
101
102 return _constructors.containsKey(clazz);
103 }
104
105 public static Object newProxyInstance(
106 ClassLoader classLoader, Class<?>[] interfaces,
107 InvocationHandler invocationHandler) {
108
109 Constructor<?> constructor = _constructors.get(
110 getProxyClass(classLoader, interfaces));
111
112 try {
113 return constructor.newInstance(new Object[] {invocationHandler});
114 }
115 catch (Exception e) {
116 throw new InternalError(e.toString());
117 }
118 }
119
120 private static Class<?>[] _argumentsClazz = {InvocationHandler.class};
121 private static ConcurrentMap
122 <ClassLoader, ConcurrentMap<LookupKey, Class<?>>> _classReferences =
123 new ConcurrentReferenceKeyHashMap
124 <ClassLoader, ConcurrentMap<LookupKey, Class<?>>>(
125 FinalizeManager.WEAK_REFERENCE_FACTORY);
126 private static ConcurrentMap<Class<?>, Constructor<?>> _constructors =
127 new ConcurrentReferenceKeyHashMap<Class<?>, Constructor<?>>(
128 FinalizeManager.WEAK_REFERENCE_FACTORY);
129 private static 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 _hashCode = 1;
147
148 for (Class<?> clazz : interfaces) {
149 String name = clazz.getName();
150
151 _hashCode = HashUtil.hash(_hashCode, name.hashCode());
152 }
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 int _hashCode;
178 private final Class<?>[] _interfaces;
179
180 }
181
182 }