001
014
015 package com.liferay.portal.test.rule;
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.ReflectionTestUtil;
022 import com.liferay.portal.kernel.test.rule.NewEnvTestRule;
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.util.SerializableUtil;
029
030 import java.io.File;
031 import java.io.Serializable;
032
033 import java.net.MalformedURLException;
034
035 import java.util.List;
036
037 import org.aspectj.lang.annotation.Aspect;
038
039 import org.junit.runner.Description;
040
041
044 public class AspectJNewEnvTestRule extends NewEnvTestRule {
045
046 public static final AspectJNewEnvTestRule INSTANCE =
047 new AspectJNewEnvTestRule();
048
049 @Override
050 protected List<String> createArguments(Description description) {
051 List<String> arguments = super.createArguments(description);
052
053 AdviseWith adviseWith = description.getAnnotation(AdviseWith.class);
054
055 if (adviseWith == null) {
056 return arguments;
057 }
058
059 Class<?>[] adviceClasses = adviseWith.adviceClasses();
060
061 if (ArrayUtil.isEmpty(adviceClasses)) {
062 return arguments;
063 }
064
065 StringBundler sb = new StringBundler(adviceClasses.length * 2 + 1);
066
067 sb.append("-DaspectClasses=");
068
069 for (Class<?> adviceClass : adviceClasses) {
070 Aspect aspect = adviceClass.getAnnotation(Aspect.class);
071
072 if (aspect == null) {
073 throw new IllegalArgumentException(
074 "Class " + adviceClass.getName() + " is not an aspect");
075 }
076
077 sb.append(adviceClass.getName());
078 sb.append(StringPool.COMMA);
079 }
080
081 sb.setIndex(sb.index() - 1);
082
083 arguments.add(sb.toString());
084
085 return arguments;
086 }
087
088 @Override
089 protected ClassLoader createClassLoader(Description description) {
090 AdviseWith adviseWith = description.getAnnotation(AdviseWith.class);
091
092 if (adviseWith == null) {
093 return super.createClassLoader(description);
094 }
095
096 Class<?>[] adviceClasses = adviseWith.adviceClasses();
097
098 if (ArrayUtil.isEmpty(adviceClasses)) {
099 return super.createClassLoader(description);
100 }
101
102 for (Class<?> adviceClass : adviceClasses) {
103 Aspect aspect = adviceClass.getAnnotation(Aspect.class);
104
105 if (aspect == null) {
106 throw new IllegalArgumentException(
107 "Class " + adviceClass.getName() + " is not an aspect");
108 }
109 }
110
111 String className = description.getClassName();
112
113 File dumpDir = new File(
114 System.getProperty("junit.aspectj.dump"),
115 className.concat(StringPool.PERIOD).concat(
116 description.getMethodName()));
117
118 try {
119 return new WeavingClassLoader(
120 ClassPathUtil.getClassPathURLs(CLASS_PATH), adviceClasses,
121 dumpDir);
122 }
123 catch (MalformedURLException murle) {
124 throw new RuntimeException(murle);
125 }
126 }
127
128 @Override
129 protected ProcessCallable<Serializable> processProcessCallable(
130 ProcessCallable<Serializable> processCallable, MethodKey methodKey) {
131
132 Class<?> clazz = methodKey.getDeclaringClass();
133
134 String className = clazz.getName();
135
136 File dumpDir = new File(
137 System.getProperty("junit.aspectj.dump"),
138 className.concat(StringPool.PERIOD).concat(
139 methodKey.getMethodName()));
140
141 return new SwitchClassLoaderProcessCallable(processCallable, dumpDir);
142 }
143
144 private AspectJNewEnvTestRule() {
145 }
146
147 private static class SwitchClassLoaderProcessCallable
148 implements ProcessCallable<Serializable> {
149
150 public SwitchClassLoaderProcessCallable(
151 ProcessCallable<Serializable> processCallable, File dumpDir) {
152
153 _dumpDir = dumpDir;
154
155 _encodedProcessCallable = SerializableUtil.serialize(
156 processCallable);
157 _toString = processCallable.toString();
158 }
159
160 @Override
161 public Serializable call() throws ProcessException {
162 attachProcess("Attached " + toString());
163
164 String[] aspectClassNames = StringUtil.split(
165 System.getProperty("aspectClasses"));
166
167 Class<?>[] aspectClasses = new Class<?>[aspectClassNames.length];
168
169 Thread currentThread = Thread.currentThread();
170
171 ClassLoader contextClassLoader =
172 currentThread.getContextClassLoader();
173
174 try {
175 for (int i = 0; i < aspectClassNames.length; i++) {
176 aspectClasses[i] = contextClassLoader.loadClass(
177 aspectClassNames[i]);
178 }
179
180 WeavingClassLoader weavingClassLoader = new WeavingClassLoader(
181 ClassPathUtil.getClassPathURLs(
182 ClassPathUtil.getJVMClassPath(true)),
183 aspectClasses, _dumpDir);
184
185 currentThread.setContextClassLoader(weavingClassLoader);
186
187 return ReflectionTestUtil.invoke(
188 SerializableUtil.deserialize(
189 _encodedProcessCallable, weavingClassLoader),
190 "call", new Class<?>[0]);
191 }
192 catch (Exception e) {
193 throw new ProcessException(e);
194 }
195 finally {
196 currentThread.setContextClassLoader(contextClassLoader);
197 }
198 }
199
200 @Override
201 public String toString() {
202 return _toString;
203 }
204
205 private static final long serialVersionUID = 1L;
206
207 private final File _dumpDir;
208 private final byte[] _encodedProcessCallable;
209 private final String _toString;
210
211 }
212
213 }