/**
* 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.aspectj;
import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
import com.liferay.portal.kernel.util.StreamUtil;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.aspectj.apache.bcel.classfile.ClassParser;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.weaver.CrosscuttingMembersSet;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.bcel.BcelObjectType;
import org.aspectj.weaver.tools.GeneratedClassHandler;
import org.aspectj.weaver.tools.WeavingAdaptor;
/**
* @author Shuyang Zhou
*/
public class URLWeavingAdapter extends WeavingAdaptor {
public URLWeavingAdapter(URL[] urls, Class<?>[] aspectClasses) {
super(null, urls, new URL[0]);
generatedClassHandler = new RecordGeneratedClassHandler();
for (Class<?> aspectClass : aspectClasses) {
_addAspectClass(aspectClass);
}
weaver.prepareForWeave();
}
public byte[] removeGeneratedClassDate(String name) {
return _generatedClasses.remove(name);
}
private void _addAspectClass(Class<?> aspectClass) {
Class<?> currentClass = aspectClass;
while (true) {
Class<?>[] interfaceClasses = currentClass.getInterfaces();
for (Class<?> interfaceClass : interfaceClasses) {
JavaClass javaClass = _classToJavaClass(interfaceClass);
if (javaClass != null) {
bcelWorld.addSourceObjectType(javaClass, false);
}
}
currentClass = currentClass.getSuperclass();
if (currentClass != null) {
JavaClass javaClass = _classToJavaClass(currentClass);
if (javaClass != null) {
bcelWorld.addSourceObjectType(javaClass, false);
}
}
else {
break;
}
}
JavaClass javaClass = _classToJavaClass(aspectClass);
BcelObjectType bcelObjectType = bcelWorld.addSourceObjectType(
javaClass, false);
ResolvedType resolvedType = bcelObjectType.getResolvedTypeX();
if (resolvedType.isAspect()) {
CrosscuttingMembersSet crosscuttingMembersSet =
bcelWorld.getCrosscuttingMembersSet();
crosscuttingMembersSet.addOrReplaceAspect(resolvedType);
}
else {
throw new IllegalArgumentException(
"Class object " + aspectClass + " is not an aspect");
}
}
private JavaClass _classToJavaClass(Class<?> aspectClass) {
ClassLoader aspectClassLoader = aspectClass.getClassLoader();
if (aspectClassLoader == null) {
aspectClassLoader = ClassLoader.getSystemClassLoader();
}
String resourcePath = aspectClass.getName();
resourcePath = resourcePath.replace('.', '/') + ".class";
ByteArrayInputStream byteArrayInputStream = null;
InputStream inputStream = aspectClassLoader.getResourceAsStream(
resourcePath);
if (inputStream instanceof ByteArrayInputStream) {
byteArrayInputStream = (ByteArrayInputStream)inputStream;
}
else {
try {
UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
new UnsyncByteArrayOutputStream();
StreamUtil.transfer(inputStream, unsyncByteArrayOutputStream);
byte[] classData =
unsyncByteArrayOutputStream.unsafeGetByteArray();
byteArrayInputStream = new ByteArrayInputStream(
classData, 0, unsyncByteArrayOutputStream.size());
}
catch (IOException ioe) {
throw new RuntimeException("Unable to reload class data", ioe);
}
}
ClassParser classParser = new ClassParser(
byteArrayInputStream, aspectClass.getSimpleName() + ".class");
try {
return classParser.parse();
}
catch (Exception e) {
throw new RuntimeException("Unable to parse class data", e);
}
}
private final Map<String, byte[]> _generatedClasses = new HashMap<>();
private class RecordGeneratedClassHandler implements GeneratedClassHandler {
@Override
public void acceptClass(
String name, byte[] originalBytes, byte[] weavedBytes) {
_generatedClasses.put(name, weavedBytes);
}
}
}