All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.portal.test.rule.AspectJNewEnvTestRule Maven / Gradle / Ivy

There is a newer version: 7.4.3.112-ga112
Show newest version
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.test.rule;

import com.liferay.petra.process.ClassPathUtil;
import com.liferay.petra.process.ProcessCallable;
import com.liferay.petra.process.ProcessException;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.aspectj.WeavingClassLoader;
import com.liferay.portal.kernel.test.ReflectionTestUtil;
import com.liferay.portal.kernel.test.rule.NewEnvTestRule;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.MethodKey;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.util.SerializableUtil;

import java.io.File;
import java.io.Serializable;

import java.net.MalformedURLException;

import java.util.List;

import org.aspectj.lang.annotation.Aspect;

import org.junit.runner.Description;

/**
 * @author Shuyang Zhou
 */
public class AspectJNewEnvTestRule extends NewEnvTestRule {

	public static final AspectJNewEnvTestRule INSTANCE =
		new AspectJNewEnvTestRule();

	@Override
	protected List createArguments(Description description) {
		List arguments = super.createArguments(description);

		AdviseWith adviseWith = description.getAnnotation(AdviseWith.class);

		if (adviseWith == null) {
			return arguments;
		}

		Class[] adviceClasses = adviseWith.adviceClasses();

		if (ArrayUtil.isEmpty(adviceClasses)) {
			return arguments;
		}

		StringBundler sb = new StringBundler(adviceClasses.length * 2 + 1);

		sb.append("-DaspectClasses=");

		for (Class adviceClass : adviceClasses) {
			Aspect aspect = adviceClass.getAnnotation(Aspect.class);

			if (aspect == null) {
				throw new IllegalArgumentException(
					"Class " + adviceClass.getName() + " is not an aspect");
			}

			sb.append(adviceClass.getName());
			sb.append(StringPool.COMMA);
		}

		sb.setIndex(sb.index() - 1);

		arguments.add(sb.toString());

		return arguments;
	}

	@Override
	protected ClassLoader createClassLoader(Description description) {
		AdviseWith adviseWith = description.getAnnotation(AdviseWith.class);

		if (adviseWith == null) {
			return super.createClassLoader(description);
		}

		Class[] adviceClasses = adviseWith.adviceClasses();

		if (ArrayUtil.isEmpty(adviceClasses)) {
			return super.createClassLoader(description);
		}

		for (Class adviceClass : adviceClasses) {
			Aspect aspect = adviceClass.getAnnotation(Aspect.class);

			if (aspect == null) {
				throw new IllegalArgumentException(
					"Class " + adviceClass.getName() + " is not an aspect");
			}
		}

		String className = description.getClassName();

		File dumpDir = new File(
			System.getProperty("junit.aspectj.dump"),
			className.concat(
				StringPool.PERIOD
			).concat(
				description.getMethodName()
			));

		try {
			return new WeavingClassLoader(
				ClassPathUtil.getClassPathURLs(CLASS_PATH), adviceClasses,
				dumpDir);
		}
		catch (MalformedURLException murle) {
			throw new RuntimeException(murle);
		}
	}

	@Override
	protected ProcessCallable processProcessCallable(
		ProcessCallable processCallable, MethodKey methodKey) {

		Class clazz = methodKey.getDeclaringClass();

		String className = clazz.getName();

		File dumpDir = new File(
			System.getProperty("junit.aspectj.dump"),
			className.concat(
				StringPool.PERIOD
			).concat(
				methodKey.getMethodName()
			));

		return new SwitchClassLoaderProcessCallable(processCallable, dumpDir);
	}

	private AspectJNewEnvTestRule() {
	}

	private static class SwitchClassLoaderProcessCallable
		implements ProcessCallable {

		public SwitchClassLoaderProcessCallable(
			ProcessCallable processCallable, File dumpDir) {

			_dumpDir = dumpDir;

			_encodedProcessCallable = SerializableUtil.serialize(
				processCallable);
			_toString = processCallable.toString();
		}

		@Override
		public Serializable call() throws ProcessException {
			attachProcess("Attached " + toString());

			String[] aspectClassNames = StringUtil.split(
				System.getProperty("aspectClasses"));

			Class[] aspectClasses = new Class[aspectClassNames.length];

			Thread currentThread = Thread.currentThread();

			ClassLoader contextClassLoader =
				currentThread.getContextClassLoader();

			try {
				for (int i = 0; i < aspectClassNames.length; i++) {
					aspectClasses[i] = contextClassLoader.loadClass(
						aspectClassNames[i]);
				}

				WeavingClassLoader weavingClassLoader = new WeavingClassLoader(
					ClassPathUtil.getClassPathURLs(
						ClassPathUtil.getJVMClassPath(true)),
					aspectClasses, _dumpDir);

				currentThread.setContextClassLoader(weavingClassLoader);

				return ReflectionTestUtil.invoke(
					SerializableUtil.deserialize(
						_encodedProcessCallable, weavingClassLoader),
					"call", new Class[0]);
			}
			catch (Exception e) {
				throw new ProcessException(e);
			}
			finally {
				currentThread.setContextClassLoader(contextClassLoader);
			}
		}

		@Override
		public String toString() {
			return _toString;
		}

		private static final long serialVersionUID = 1L;

		private final File _dumpDir;
		private final byte[] _encodedProcessCallable;
		private final String _toString;

	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy