001
014
015 package com.liferay.portal.test.runners;
016
017 import com.liferay.portal.aspectj.WeavingClassLoader;
018 import com.liferay.portal.kernel.process.ClassPathUtil;
019 import com.liferay.portal.kernel.process.ProcessCallable;
020 import com.liferay.portal.kernel.process.ProcessException;
021 import com.liferay.portal.kernel.test.NewJVMJUnitTestRunner;
022 import com.liferay.portal.kernel.test.ReflectionTestUtil;
023 import com.liferay.portal.kernel.util.ArrayUtil;
024 import com.liferay.portal.kernel.util.MethodKey;
025 import com.liferay.portal.kernel.util.StringBundler;
026 import com.liferay.portal.kernel.util.StringPool;
027 import com.liferay.portal.kernel.util.StringUtil;
028 import com.liferay.portal.test.AdviseWith;
029 import com.liferay.util.SerializableUtil;
030
031 import java.io.File;
032 import java.io.Serializable;
033
034 import java.net.URL;
035
036 import java.util.Collections;
037 import java.util.List;
038
039 import org.aspectj.lang.annotation.Aspect;
040
041 import org.junit.runners.model.FrameworkMethod;
042 import org.junit.runners.model.InitializationError;
043
044
047 public class AspectJMockingNewJVMJUnitTestRunner extends NewJVMJUnitTestRunner {
048
049 public AspectJMockingNewJVMJUnitTestRunner(Class<?> clazz)
050 throws InitializationError {
051
052 super(clazz);
053 }
054
055 @Override
056 protected List<String> createArguments(FrameworkMethod frameworkMethod) {
057 List<String> arguments = super.createArguments(frameworkMethod);
058
059 AdviseWith adviseWith = frameworkMethod.getAnnotation(AdviseWith.class);
060
061 if (adviseWith == null) {
062 return arguments;
063 }
064
065 Class<?>[] adviceClasses = adviseWith.adviceClasses();
066
067 if (ArrayUtil.isEmpty(adviceClasses)) {
068 return Collections.emptyList();
069 }
070
071 StringBundler sb = new StringBundler(adviceClasses.length * 2 + 1);
072
073 sb.append("-DaspectClasses=");
074
075 for (Class<?> adviceClass : adviceClasses) {
076 Aspect aspect = adviceClass.getAnnotation(Aspect.class);
077
078 if (aspect == null) {
079 throw new IllegalArgumentException(
080 "Class " + adviceClass.getName() + " is not an aspect");
081 }
082
083 sb.append(adviceClass.getName());
084 sb.append(StringPool.COMMA);
085 }
086
087 sb.setIndex(sb.index() - 1);
088
089 arguments.add(sb.toString());
090
091 return arguments;
092 }
093
094 @Override
095 protected ProcessCallable<Serializable> processProcessCallable(
096 ProcessCallable<Serializable> processCallable, MethodKey methodKey) {
097
098 String dumpDirName = System.getProperty("junit.aspectj.dump");
099
100 Class<?> clazz = methodKey.getDeclaringClass();
101
102 String className = clazz.getName();
103
104 File dumpDir = new File(
105 dumpDirName,
106 className.concat(StringPool.PERIOD).concat(
107 methodKey.getMethodName()));
108
109 return new SwitchClassLoaderProcessCallable(processCallable, dumpDir);
110 }
111
112 private static class SwitchClassLoaderProcessCallable
113 implements ProcessCallable<Serializable> {
114
115 public SwitchClassLoaderProcessCallable(
116 ProcessCallable<Serializable> processCallable, File dumpDir) {
117
118 _dumpDir = dumpDir;
119
120 _encodedProcessCallable = SerializableUtil.serialize(
121 processCallable);
122
123 _toString = processCallable.toString();
124 }
125
126 @Override
127 public Serializable call() throws ProcessException {
128 attachProcess("Attached " + toString());
129
130 String[] aspectClassNames = StringUtil.split(
131 System.getProperty("aspectClasses"));
132
133 Class<?>[] aspectClasses = new Class<?>[aspectClassNames.length];
134
135 Thread currentThread = Thread.currentThread();
136
137 ClassLoader contextClassLoader =
138 currentThread.getContextClassLoader();
139
140 String jvmClassPath = ClassPathUtil.getJVMClassPath(true);
141
142 try {
143 URL[] urls = ClassPathUtil.getClassPathURLs(jvmClassPath);
144
145 for (int i = 0; i < aspectClassNames.length; i++) {
146 aspectClasses[i] = contextClassLoader.loadClass(
147 aspectClassNames[i]);
148 }
149
150 WeavingClassLoader weavingClassLoader = new WeavingClassLoader(
151 urls, aspectClasses, _dumpDir);
152
153 Object originalProcessCallable = SerializableUtil.deserialize(
154 _encodedProcessCallable, weavingClassLoader);
155
156 currentThread.setContextClassLoader(weavingClassLoader);
157
158 return ReflectionTestUtil.invoke(
159 originalProcessCallable, "call", new Class<?>[0]);
160 }
161 catch (Exception e) {
162 throw new ProcessException(e);
163 }
164 finally {
165 currentThread.setContextClassLoader(contextClassLoader);
166 }
167 }
168
169 @Override
170 public String toString() {
171 return _toString;
172 }
173
174 private static final long serialVersionUID = 1L;
175
176 private File _dumpDir;
177 private byte[] _encodedProcessCallable;
178 private String _toString;
179 }
180
181 }