001
014
015 package com.liferay.portal.test;
016
017 import com.liferay.portal.deploy.hot.HookHotDeployListener;
018 import com.liferay.portal.deploy.hot.IndexerPostProcessorRegistry;
019 import com.liferay.portal.deploy.hot.SchedulerEntryRegistry;
020 import com.liferay.portal.deploy.hot.ServiceWrapperRegistry;
021 import com.liferay.portal.kernel.deploy.hot.DependencyManagementThreadLocal;
022 import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
023 import com.liferay.portal.kernel.deploy.hot.HotDeployUtil;
024 import com.liferay.portal.kernel.portlet.PortletClassLoaderUtil;
025 import com.liferay.portal.kernel.servlet.ServletContextPool;
026 import com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterHelper;
027 import com.liferay.portal.kernel.test.BaseTestRule;
028 import com.liferay.portal.kernel.util.ClassLoaderPool;
029 import com.liferay.portal.kernel.util.ListUtil;
030 import com.liferay.portal.kernel.util.PortalLifecycleUtil;
031 import com.liferay.portal.kernel.util.PropsKeys;
032 import com.liferay.portal.kernel.util.StringPool;
033 import com.liferay.portal.service.ServiceTestUtil;
034 import com.liferay.portal.spring.context.PortletContextLoaderListener;
035 import com.liferay.portal.test.mock.AutoDeployMockServletContext;
036 import com.liferay.portal.util.InitUtil;
037 import com.liferay.portal.util.PortalUtil;
038 import com.liferay.portal.util.PropsUtil;
039
040 import java.lang.reflect.Method;
041
042 import java.net.MalformedURLException;
043 import java.net.URL;
044 import java.net.URLClassLoader;
045
046 import java.security.CodeSource;
047 import java.security.ProtectionDomain;
048
049 import java.util.List;
050 import java.util.Map;
051 import java.util.concurrent.ConcurrentHashMap;
052
053 import javax.naming.Context;
054
055 import javax.servlet.ServletContext;
056 import javax.servlet.ServletContextEvent;
057
058 import org.junit.runner.Description;
059 import org.junit.runners.model.Statement;
060
061 import org.springframework.core.io.ClassPathResource;
062 import org.springframework.core.io.FileSystemResourceLoader;
063 import org.springframework.core.io.Resource;
064 import org.springframework.core.io.ResourceLoader;
065 import org.springframework.mock.web.MockServletContext;
066
067
071 public class PACLTestRule extends BaseTestRule<HotDeployEvent, Object> {
072
073 public static final String RESOURCE_PATH =
074 "com/liferay/portal/security/pacl/test/dependencies";
075
076 @Override
077 protected void afterClass(
078 Description description, HotDeployEvent hotDeployEvent) {
079
080 HotDeployUtil.fireUndeployEvent(hotDeployEvent);
081
082 PortletContextLoaderListener portletContextLoaderListener =
083 new PortletContextLoaderListener();
084
085 ClassLoaderPool.register(
086 hotDeployEvent.getServletContextName(),
087 hotDeployEvent.getContextClassLoader());
088 PortletClassLoaderUtil.setServletContextName(
089 hotDeployEvent.getServletContextName());
090
091 try {
092 portletContextLoaderListener.contextDestroyed(
093 new ServletContextEvent(hotDeployEvent.getServletContext()));
094 }
095 finally {
096 ClassLoaderPool.unregister(hotDeployEvent.getServletContextName());
097 PortletClassLoaderUtil.setServletContextName(null);
098 }
099 }
100
101 @Override
102 protected HotDeployEvent beforeClass(Description description)
103 throws ReflectiveOperationException {
104
105 _testClass = _loadTestClass(description.getTestClass());
106 _instance = _testClass.newInstance();
107
108 ServletContext servletContext = ServletContextPool.get(
109 PortalUtil.getServletContextName());
110
111 if (servletContext == null) {
112 servletContext = new AutoDeployMockServletContext(
113 new FileSystemResourceLoader());
114
115 servletContext.setAttribute(
116 InvokerFilterHelper.class.getName(), new InvokerFilterHelper());
117
118 ServletContextPool.put(PortalUtil.getPathContext(), servletContext);
119 }
120
121 HotDeployUtil.reset();
122
123 HotDeployUtil.registerListener(new HookHotDeployListener());
124
125 HotDeployUtil.setCapturePrematureEvents(false);
126
127 PortalLifecycleUtil.flushInits();
128
129 ClassLoader classLoader = _testClass.getClassLoader();
130
131 MockServletContext mockServletContext = new MockServletContext(
132 new PACLResourceLoader(classLoader));
133
134 mockServletContext.setServletContextName("a-test-hook");
135
136 HotDeployEvent hotDeployEvent = getHotDeployEvent(
137 mockServletContext, classLoader);
138
139 HotDeployUtil.fireDeployEvent(hotDeployEvent);
140
141 PortletContextLoaderListener portletContextLoaderListener =
142 new PortletContextLoaderListener();
143
144 ClassLoaderPool.register(
145 hotDeployEvent.getServletContextName(),
146 hotDeployEvent.getContextClassLoader());
147 PortletClassLoaderUtil.setServletContextName(
148 hotDeployEvent.getServletContextName());
149
150 try {
151 portletContextLoaderListener.contextInitialized(
152 new ServletContextEvent(mockServletContext));
153 }
154 finally {
155 ClassLoaderPool.unregister(hotDeployEvent.getServletContextName());
156 PortletClassLoaderUtil.setServletContextName(null);
157 }
158
159 return hotDeployEvent;
160 }
161
162 protected HotDeployEvent getHotDeployEvent(
163 ServletContext servletContext, ClassLoader classLoader) {
164
165 boolean dependencyManagementEnabled =
166 DependencyManagementThreadLocal.isEnabled();
167
168 try {
169 DependencyManagementThreadLocal.setEnabled(false);
170
171 return new HotDeployEvent(servletContext, classLoader);
172 }
173 finally {
174 DependencyManagementThreadLocal.setEnabled(
175 dependencyManagementEnabled);
176 }
177 }
178
179 @Override
180 protected void invokeStatement(Statement statement, Description description)
181 throws Throwable {
182
183 String methodName = description.getMethodName();
184
185 if (methodName == null) {
186 statement.evaluate();
187
188 return;
189 }
190
191 Method method = _testClass.getMethod(description.getMethodName());
192
193 method.invoke(_instance);
194 }
195
196 private static Class<?> _loadTestClass(Class<?> clazz)
197 throws ClassNotFoundException {
198
199 ProtectionDomain protectionDomain = clazz.getProtectionDomain();
200
201 CodeSource codeSource = protectionDomain.getCodeSource();
202
203 ClassLoader classLoader = new PACLClassLoader(
204 new URL[] {codeSource.getLocation()}, clazz.getClassLoader());
205
206 return Class.forName(clazz.getName(), true, classLoader);
207 }
208
209 private static final String _PACKAGE_PATH =
210 "com.liferay.portal.security.pacl.test.";
211
212 static {
213 URL resource = PACLTestRule.class.getResource("pacl-test.properties");
214
215 if (resource != null) {
216 System.setProperty("external-properties", resource.getPath());
217 }
218
219 System.setProperty(
220 Context.INITIAL_CONTEXT_FACTORY,
221 "org.apache.naming.java.javaURLContextFactory");
222
223 System.setProperty("catalina.base", ".");
224
225 List<String> configLocations = ListUtil.fromArray(
226 PropsUtil.getArray(PropsKeys.SPRING_CONFIGS));
227
228 InitUtil.initWithSpring(configLocations, true);
229
230 ServiceTestUtil.initServices();
231 ServiceTestUtil.initPermissions();
232
233 new IndexerPostProcessorRegistry();
234 new SchedulerEntryRegistry();
235 new ServiceWrapperRegistry();
236 }
237
238 private Object _instance;
239 private Class<?> _testClass;
240
241 private static class PACLClassLoader extends URLClassLoader {
242
243 public PACLClassLoader(URL[] urls, ClassLoader parentClassLoader) {
244 super(urls, parentClassLoader);
245 }
246
247 @Override
248 public URL findResource(String name) {
249 if (_urls.containsKey(name)) {
250 return _urls.get(name);
251 }
252
253 URL resource = null;
254
255 if (!name.contains(RESOURCE_PATH)) {
256 String newName = name;
257
258 if (!newName.startsWith(StringPool.SLASH)) {
259 newName = StringPool.SLASH.concat(newName);
260 }
261
262 newName = RESOURCE_PATH.concat(newName);
263
264 resource = super.findResource(newName);
265 }
266
267 if ((resource == null) && !name.contains(RESOURCE_PATH)) {
268 String newName = name;
269
270 if (!newName.startsWith(StringPool.SLASH)) {
271 newName = StringPool.SLASH.concat(newName);
272 }
273
274 newName = RESOURCE_PATH.concat("/WEB-INF/classes").concat(
275 newName);
276
277 resource = super.findResource(newName);
278 }
279
280 if (resource == null) {
281 resource = super.findResource(name);
282 }
283
284 if (resource != null) {
285 _urls.put(name, resource);
286 }
287
288 return resource;
289 }
290
291 @Override
292 public URL getResource(String name) {
293 if (name.equals(
294 "com/liferay/util/bean/PortletBeanLocatorUtil.class")) {
295
296 URL url = findResource("/");
297
298 String path = url.getPath();
299
300 path = path.substring(
301 0, path.length() - RESOURCE_PATH.length() - 1);
302
303 path = path.concat(name);
304
305 try {
306 return new URL("file", null, path);
307 }
308 catch (MalformedURLException murle) {
309 }
310 }
311
312 URL url = findResource(name);
313
314 if (url != null) {
315 return url;
316 }
317
318 return super.getResource(name);
319 }
320
321 @Override
322 public Class<?> loadClass(String name) throws ClassNotFoundException {
323 if (name.startsWith(_PACKAGE_PATH)) {
324 if (_classes.containsKey(name)) {
325 return _classes.get(name);
326 }
327
328 Class<?> clazz = super.findClass(name);
329
330 _classes.put(name, clazz);
331
332 return clazz;
333 }
334
335 return super.loadClass(name);
336 }
337
338 @Override
339 protected synchronized Class<?> loadClass(String name, boolean resolve)
340 throws ClassNotFoundException {
341
342 if (name.startsWith(_PACKAGE_PATH)) {
343 if (_classes.containsKey(name)) {
344 return _classes.get(name);
345 }
346
347 Class<?> clazz = super.findClass(name);
348
349 _classes.put(name, clazz);
350
351 return clazz;
352 }
353
354 return super.loadClass(name, resolve);
355 }
356
357 private final Map<String, Class<?>> _classes =
358 new ConcurrentHashMap<String, Class<?>>();
359 private final Map<String, URL> _urls =
360 new ConcurrentHashMap<String, URL>();
361
362 }
363
364 private static class PACLResourceLoader implements ResourceLoader {
365
366 public PACLResourceLoader(ClassLoader classLoader) {
367 _classLoader = classLoader;
368 }
369
370 @Override
371 public ClassLoader getClassLoader() {
372 return _classLoader;
373 }
374
375 @Override
376 public Resource getResource(String location) {
377 ClassLoader classLoader = getClassLoader();
378
379 return new ClassPathResource(RESOURCE_PATH + location, classLoader);
380 }
381
382 private final ClassLoader _classLoader;
383
384 }
385
386 }