001
014
015 package com.liferay.portal.aspectj;
016
017 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
018 import com.liferay.portal.kernel.util.StreamUtil;
019
020 import java.io.ByteArrayInputStream;
021 import java.io.IOException;
022 import java.io.InputStream;
023
024 import java.net.URL;
025
026 import java.util.HashMap;
027 import java.util.Map;
028
029 import org.aspectj.apache.bcel.classfile.ClassParser;
030 import org.aspectj.apache.bcel.classfile.JavaClass;
031 import org.aspectj.weaver.CrosscuttingMembersSet;
032 import org.aspectj.weaver.ResolvedType;
033 import org.aspectj.weaver.bcel.BcelObjectType;
034 import org.aspectj.weaver.tools.GeneratedClassHandler;
035 import org.aspectj.weaver.tools.WeavingAdaptor;
036
037
040 public class URLWeavingAdaptor extends WeavingAdaptor {
041
042 public URLWeavingAdaptor(URL[] urls, Class<?>[] aspectClasses) {
043 super(null, urls, new URL[0]);
044
045 generatedClassHandler = new RecordGeneratedClassHandler();
046
047 for (Class<?> aspectClass : aspectClasses) {
048 _addAspectClass(aspectClass);
049 }
050
051 weaver.prepareForWeave();
052 }
053
054 public byte[] removeGeneratedClassDate(String name) {
055 return _generatedClasses.remove(name);
056 }
057
058 private void _addAspectClass(Class<?> aspectClass) {
059 Class<?> currentClass = aspectClass;
060
061 while (true) {
062 Class<?>[] interfaceClasses = currentClass.getInterfaces();
063
064 for (Class<?> interfaceClass : interfaceClasses) {
065 JavaClass javaClass = _classToJavaClass(interfaceClass);
066
067 if (javaClass != null) {
068 bcelWorld.addSourceObjectType(javaClass, false);
069 }
070 }
071
072 currentClass = currentClass.getSuperclass();
073
074 if (currentClass != null) {
075 JavaClass javaClass = _classToJavaClass(currentClass);
076
077 if (javaClass != null) {
078 bcelWorld.addSourceObjectType(javaClass, false);
079 }
080 }
081 else {
082 break;
083 }
084 }
085
086 JavaClass javaClass = _classToJavaClass(aspectClass);
087
088 BcelObjectType bcelObjectType = bcelWorld.addSourceObjectType(
089 javaClass, false);
090
091 ResolvedType resolvedType = bcelObjectType.getResolvedTypeX();
092
093 if (resolvedType.isAspect()) {
094 CrosscuttingMembersSet crosscuttingMembersSet =
095 bcelWorld.getCrosscuttingMembersSet();
096
097 crosscuttingMembersSet.addOrReplaceAspect(resolvedType);
098 }
099 else {
100 throw new IllegalArgumentException(
101 "Class object " + aspectClass + " is not an aspect");
102 }
103 }
104
105 private JavaClass _classToJavaClass(Class<?> aspectClass) {
106 ClassLoader aspectClassLoader = aspectClass.getClassLoader();
107
108 if (aspectClassLoader == null) {
109 aspectClassLoader = ClassLoader.getSystemClassLoader();
110 }
111
112 String resourcePath = aspectClass.getName();
113
114 resourcePath = resourcePath.replace('.', '/') + ".class";
115
116 ByteArrayInputStream byteArrayInputStream = null;
117
118 InputStream inputStream = aspectClassLoader.getResourceAsStream(
119 resourcePath);
120
121 if (inputStream instanceof ByteArrayInputStream) {
122 byteArrayInputStream = (ByteArrayInputStream)inputStream;
123 }
124 else {
125 try {
126 UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
127 new UnsyncByteArrayOutputStream();
128
129 StreamUtil.transfer(
130 inputStream, unsyncByteArrayOutputStream, true);
131
132 byte[] classData =
133 unsyncByteArrayOutputStream.unsafeGetByteArray();
134
135 byteArrayInputStream = new ByteArrayInputStream(
136 classData, 0, unsyncByteArrayOutputStream.size());
137 }
138 catch (IOException ioe) {
139 throw new RuntimeException("Unable to reload class data", ioe);
140 }
141 }
142
143 ClassParser classParser = new ClassParser(
144 byteArrayInputStream, aspectClass.getSimpleName() + ".class");
145
146 try {
147 return classParser.parse();
148 }
149 catch (Exception e) {
150 throw new RuntimeException("Unable to parse class data", e);
151 }
152 }
153
154 private Map<String, byte[]> _generatedClasses =
155 new HashMap<String, byte[]>();
156
157 private class RecordGeneratedClassHandler implements GeneratedClassHandler {
158
159 @Override
160 public void acceptClass(String name, byte[] bytes) {
161 _generatedClasses.put(name, bytes);
162 }
163
164 }
165
166 }