001
014
015 package com.liferay.portal.security.pacl;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.util.AggregateClassLoader;
020 import com.liferay.portal.kernel.util.ProxyUtil;
021 import com.liferay.portal.kernel.util.ServerDetector;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.StringUtil;
024 import com.liferay.portal.security.lang.PortalSecurityManagerThreadLocal;
025 import com.liferay.portal.spring.util.FilterClassLoader;
026
027 import java.net.URL;
028
029 import sun.reflect.Reflection;
030
031
034 public class PACLClassUtil {
035
036 public static ClassLoader getCallerClassLoader(Class<?> callerClass) {
037 boolean enabled = PortalSecurityManagerThreadLocal.isEnabled();
038
039 try {
040 PortalSecurityManagerThreadLocal.setEnabled(false);
041
042 return _instance._getCallerClassLoader(callerClass);
043 }
044 finally {
045 PortalSecurityManagerThreadLocal.setEnabled(enabled);
046 }
047 }
048
049 public static String getClassLocation(Class<?> clazz) {
050 boolean enabled = PortalSecurityManagerThreadLocal.isEnabled();
051
052 try {
053 PortalSecurityManagerThreadLocal.setEnabled(false);
054
055 ClassLoader classLoader = clazz.getClassLoader();
056
057 if (classLoader == null) {
058 return StringPool.BLANK;
059 }
060
061 String className = clazz.getName();
062
063 String name = StringUtil.replace(
064 className, StringPool.PERIOD, StringPool.SLASH);
065
066 name += ".class";
067
068 URL url = classLoader.getResource(name);
069
070 return url.toString();
071 }
072 finally {
073 PortalSecurityManagerThreadLocal.setEnabled(enabled);
074 }
075 }
076
077 public static String getJarLocation(Class<?> clazz) {
078 String classLocation = getClassLocation(clazz);
079
080 if (classLocation == null) {
081 return null;
082 }
083
084 int index = classLocation.indexOf(".jar!");
085
086 return classLocation.substring(0, index + 4);
087 }
088
089 public static PACLPolicy getPACLPolicy(boolean deep, boolean debug) {
090 PACLPolicy paclPolicy =
091 PortalSecurityManagerThreadLocal.getPACLPolicy();
092
093 if (paclPolicy != null) {
094 return paclPolicy;
095 }
096
097 return getPACLPolicyByReflection(deep, debug);
098 }
099
100 public static PACLPolicy getPACLPolicyByReflection(
101 boolean deep, boolean debug) {
102
103 boolean enabled = PortalSecurityManagerThreadLocal.isEnabled();
104
105 try {
106 PortalSecurityManagerThreadLocal.setEnabled(false);
107
108 return _instance._getPACLPolicyByReflection(deep, debug);
109 }
110 finally {
111 PortalSecurityManagerThreadLocal.setEnabled(enabled);
112 }
113 }
114
115 private PACLClassUtil() {
116 _systemClassLoader = ClassLoader.getSystemClassLoader();
117
118 _portalClassLoader = PACLAdvice.class.getClassLoader();
119
120 _commonClassLoader = _portalClassLoader.getParent();
121 }
122
123 private ClassLoader _getCallerClassLoader(Class<?> callerClass) {
124 ClassLoader callerClassLoader = callerClass.getClassLoader();
125
126 if (callerClassLoader == null) {
127 return null;
128 }
129
130 Class<?> callerClassLoaderClass = callerClassLoader.getClass();
131
132 String callerClassLoaderClassName = callerClassLoaderClass.getName();
133
134 if (callerClassLoader instanceof FilterClassLoader) {
135 callerClassLoader = callerClassLoader.getParent();
136
137 if (callerClassLoader instanceof AggregateClassLoader) {
138 callerClassLoader = callerClassLoader.getParent();
139 }
140 }
141
142 if (callerClassLoaderClassName.equals(_ClASS_NAME_JASPER_LOADER)) {
143 callerClassLoader = callerClassLoader.getParent();
144 }
145 else if (ServerDetector.isResin()) {
146 if (callerClassLoaderClassName.equals(
147 _ClASS_NAME_DYNAMIC_CLASS_LOADER)) {
148
149 callerClassLoader = callerClassLoader.getParent();
150 }
151 }
152 else if (ServerDetector.isWebLogic()) {
153 if (callerClassLoaderClassName.equals(
154 _CLASS_NAME_JSP_CLASS_LOADER)) {
155
156
157
158 callerClassLoader = callerClassLoader.getParent();
159
160
161
162 callerClassLoader = callerClassLoader.getParent();
163 }
164 }
165 else if (ServerDetector.isWebSphere()) {
166 if (callerClassLoaderClassName.equals(
167 _CLASS_NAME_JSP_EXTENSION_CLASS_LOADER)) {
168
169 callerClassLoader = callerClassLoader.getParent();
170 }
171 }
172
173 return callerClassLoader;
174 }
175
176 private PACLPolicy _getPACLPolicyByReflection(boolean deep, boolean debug) {
177 PACLPolicy paclPolicy = null;
178
179 boolean initialPortalClassLoaderPhase = true;
180
181
182
183 for (int i = 1;; i++) {
184 Class<?> callerClass = Reflection.getCallerClass(i);
185
186 if (callerClass == null) {
187 break;
188 }
189
190 if (debug) {
191 _log.debug(
192 "Frame " + i + " has caller class " +
193 callerClass.getName());
194 }
195
196 if (ProxyUtil.isProxyClass(callerClass)) {
197 if (debug) {
198 _log.debug("Skipping frame because it is proxy class");
199 }
200
201 continue;
202 }
203
204 ClassLoader callerClassLoader = _getCallerClassLoader(callerClass);
205
206 if (callerClassLoader == null) {
207 continue;
208 }
209
210
226
227 if (!initialPortalClassLoaderPhase &&
228 (callerClassLoader == _portalClassLoader)) {
229
230 PACLPolicy defaultPACLPolicy =
231 PACLPolicyManager.getDefaultPACLPolicy();
232
233 if (paclPolicy == null) {
234 if (debug) {
235 _log.debug(
236 "Possibly return default PACL policy " +
237 defaultPACLPolicy);
238 }
239
240 paclPolicy = defaultPACLPolicy;
241 }
242
243 if (!deep) {
244 break;
245 }
246
247 continue;
248 }
249
250 if (initialPortalClassLoaderPhase &&
251 (callerClassLoader != _portalClassLoader)) {
252
253 initialPortalClassLoaderPhase = false;
254 }
255
256 if ((callerClassLoader == _commonClassLoader) ||
257 (callerClassLoader == _portalClassLoader) ||
258 (callerClassLoader == _systemClassLoader)) {
259
260 continue;
261 }
262
263 if (debug) {
264 _log.debug(
265 "Lookup PACL policy for caller class loader " +
266 callerClassLoader);
267 }
268
269 PACLPolicy callerPACLPolicy = PACLPolicyManager.getPACLPolicy(
270 callerClassLoader);
271
272 if (callerPACLPolicy != null) {
273 paclPolicy = callerPACLPolicy;
274
275 if (debug) {
276 _log.debug("Possibly return PACL policy " + paclPolicy);
277 }
278
279 if (!deep) {
280 break;
281 }
282 }
283 }
284
285 if (debug) {
286 _log.debug("Returning PACL policy " + paclPolicy);
287 }
288
289 return paclPolicy;
290 }
291
292 private static final String _ClASS_NAME_DYNAMIC_CLASS_LOADER =
293 "com.caucho.loader.DynamicClassLoader";
294
295 private static final String _ClASS_NAME_JASPER_LOADER =
296 "org.apache.jasper.servlet.JasperLoader";
297
298 private static final String _CLASS_NAME_JSP_CLASS_LOADER =
299 "weblogic.servlet.jsp.JspClassLoader";
300
301 private static final String _CLASS_NAME_JSP_EXTENSION_CLASS_LOADER =
302 "com.ibm.ws.jsp.webcontainerext.JSPExtensionClassLoader";
303
304 private static Log _log = LogFactoryUtil.getLog(PACLClassUtil.class);
305
306 private static PACLClassUtil _instance = new PACLClassUtil();
307
308 private ClassLoader _commonClassLoader;
309 private ClassLoader _portalClassLoader;
310 private ClassLoader _systemClassLoader;
311
312 }