001
014
015 package com.liferay.portal.security.lang;
016
017 import com.liferay.portal.kernel.security.pacl.NotPrivileged;
018 import com.liferay.portal.kernel.security.pacl.permission.PortalServicePermission;
019 import com.liferay.portal.kernel.util.HashUtil;
020 import com.liferay.portal.kernel.util.Validator;
021
022 import java.lang.reflect.InvocationHandler;
023 import java.lang.reflect.InvocationTargetException;
024 import java.lang.reflect.Method;
025
026 import java.security.AccessController;
027 import java.security.PrivilegedActionException;
028 import java.security.PrivilegedExceptionAction;
029
030 import java.util.ArrayList;
031 import java.util.Arrays;
032 import java.util.Collections;
033 import java.util.List;
034
035
038 public class DoPrivilegedHandler
039 implements DoPrivilegedBean, InvocationHandler {
040
041 public DoPrivilegedHandler(Object bean) {
042 _bean = bean;
043
044 _initNotPrivilegedMethods();
045 }
046
047 @Override
048 public Object getActualBean() {
049 return _bean;
050 }
051
052 @Override
053 public Object invoke(Object proxy, Method method, Object[] arguments)
054 throws Throwable {
055
056 try {
057 return doInvoke(proxy, method, arguments);
058 }
059 catch (InvocationTargetException ite) {
060 throw ite.getTargetException();
061 }
062 }
063
064 protected Object doInvoke(Object proxy, Method method, Object[] arguments)
065 throws Throwable {
066
067 Class<?> methodDeclaringClass = method.getDeclaringClass();
068 String methodName = method.getName();
069
070 if (methodDeclaringClass.equals(DoPrivilegedBean.class) &&
071 methodName.equals("getActualBean")) {
072
073 return _bean;
074 }
075 else if (methodDeclaringClass.equals(Object.class) &&
076 methodName.equals("equals")) {
077
078 Object object = arguments[0];
079
080 if (object instanceof DoPrivilegedBean) {
081 DoPrivilegedBean doPrivilegedBean = (DoPrivilegedBean)object;
082
083 object = doPrivilegedBean.getActualBean();
084 }
085
086 return _bean.equals(object);
087 }
088 else if (_isNotPrivileged(method)) {
089 return method.invoke(_bean, arguments);
090 }
091
092 String declaringClassName = methodDeclaringClass.getName();
093
094 if (declaringClassName.endsWith(_BEAN_NAME_SUFFIX_FINDER) ||
095 declaringClassName.endsWith(_BEAN_NAME_SUFFIX_PERSISTENCE)) {
096
097 PortalServicePermission.checkService(_bean, method, arguments);
098 }
099
100 try {
101 return AccessController.doPrivileged(
102 new InvokePrivilegedExceptionAction(_bean, method, arguments));
103 }
104 catch (PrivilegedActionException pae) {
105 Exception e = pae.getException();
106
107 throw e.getCause();
108 }
109 }
110
111 private void _initNotPrivilegedMethods() {
112 _notPrivilegedMethods = new ArrayList<>();
113
114 Class<?> beanClass = _bean.getClass();
115
116 Method[] methods = beanClass.getMethods();
117
118 for (Method method : methods) {
119 NotPrivileged notPrivileged = method.getAnnotation(
120 NotPrivileged.class);
121
122 if (notPrivileged == null) {
123 continue;
124 }
125
126 _notPrivilegedMethods.add(new MethodKey(method));
127 }
128
129 _notPrivilegedMethods = Collections.unmodifiableList(
130 _notPrivilegedMethods);
131
132 if (!_notPrivilegedMethods.isEmpty()) {
133 _hasNotPrivilegedMethods = true;
134 }
135 }
136
137 private boolean _isNotPrivileged(Method method) {
138 if (_hasNotPrivilegedMethods &&
139 _notPrivilegedMethods.contains(new MethodKey(method))) {
140
141 return true;
142 }
143
144 return false;
145 }
146
147 private static final String _BEAN_NAME_SUFFIX_FINDER = "Finder";
148
149 private static final String _BEAN_NAME_SUFFIX_PERSISTENCE = "Persistence";
150
151 private Object _bean;
152 private boolean _hasNotPrivilegedMethods = false;
153 private List<MethodKey> _notPrivilegedMethods;
154
155 private class InvokePrivilegedExceptionAction
156 implements PrivilegedExceptionAction<Object> {
157
158 public InvokePrivilegedExceptionAction(
159 Object bean, Method method, Object[] arguments) {
160
161 _bean = bean;
162 _method = method;
163 _arguments = arguments;
164 }
165
166 @Override
167 public Object run() throws Exception {
168 return _method.invoke(_bean, _arguments);
169 }
170
171 private final Object[] _arguments;
172 private Object _bean;
173 private final Method _method;
174
175 }
176
177
183 private class MethodKey {
184
185 public MethodKey(Method method) {
186 _declaringClass = method.getDeclaringClass();
187 _methodName = method.getName();
188 _parameterTypes = method.getParameterTypes();
189 }
190
191 @Override
192 public boolean equals(Object obj) {
193 MethodKey methodKey = (MethodKey)obj;
194
195
196
197
198 if (_declaringClass.isAssignableFrom(methodKey._declaringClass) &&
199 Validator.equals(_methodName, methodKey._methodName) &&
200 Arrays.equals(_parameterTypes, methodKey._parameterTypes)) {
201
202 return true;
203 }
204
205 return false;
206 }
207
208 @Override
209 public int hashCode() {
210 int hash = HashUtil.hash(0, _declaringClass);
211
212 hash = HashUtil.hash(hash, _methodName);
213
214 return HashUtil.hash(hash, _parameterTypes);
215 }
216
217 private final Class<?> _declaringClass;
218 private final String _methodName;
219 private final Class<?>[] _parameterTypes;
220
221 }
222
223 }