Created
May 9, 2018 18:05
-
-
Save Andrei-Pozolotin/1c3b9da1bb6d1edbbcea22471520dc07 to your computer and use it in GitHub Desktop.
How to AOP aspectj in OSGi with Apache Felix https://stackoverflow.com/questions/37786309/how-to-aop-aspectj-in-osgi-with-apache-felix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.carrotgarden.base.osgi_aj; | |
import java.util.ArrayList; | |
import java.util.List; | |
import org.osgi.framework.BundleActivator; | |
import org.osgi.framework.BundleContext; | |
import org.osgi.framework.ServiceRegistration; | |
import org.osgi.framework.hooks.weaving.WeavingHook; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
public class Activator implements BundleActivator { | |
static Logger logger = LoggerFactory.getLogger(Activator.class); | |
List<ServiceRegistration<?>> servList = new ArrayList<>(); | |
public void start(BundleContext context) throws Exception { | |
logger.info("starting: {}", Activator.class.getName()); | |
AspectWeaver weaver = new AspectWeaver(); | |
servList.add(context.registerService(WeavingHook.class, weaver, null)); | |
servList.add(context.registerService(AspectWeaver.class, weaver, null)); | |
} | |
public void stop(BundleContext context) throws Exception { | |
for (ServiceRegistration<?> serv : servList) { | |
serv.unregister(); | |
} | |
logger.info("stopping: {}", Activator.class.getName()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.carrotgarden.base.osgi_aj; | |
import java.util.List; | |
import org.aspectj.weaver.loadtime.DefaultWeavingContext; | |
import org.aspectj.weaver.loadtime.definition.Definition; | |
import org.aspectj.weaver.tools.WeavingAdaptor; | |
import org.osgi.framework.wiring.BundleWiring; | |
public class AspectContext extends DefaultWeavingContext { | |
protected BundleWiring wiring; | |
protected volatile List<Definition> definitionList; | |
protected String rootConfig = "org/aspectj/osgi.xml"; | |
public AspectContext(BundleWiring wiring) { | |
super(wiring.getClassLoader()); | |
this.wiring = wiring; | |
} | |
@Override | |
public String getId() { | |
return getClassLoaderName(); | |
} | |
@Override | |
public String getClassLoaderName() { | |
return wiring.getRevision().getSymbolicName(); | |
} | |
@Override | |
public List<Definition> getDefinitions(final ClassLoader loader, final WeavingAdaptor adaptor) { | |
if (definitionList == null) { | |
definitionList = AspectSupport.definitionList(loader, rootConfig); | |
} | |
return definitionList; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.carrotgarden.base.osgi_aj; | |
import java.net.URL; | |
import java.util.ArrayList; | |
import java.util.Enumeration; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import org.aspectj.weaver.loadtime.definition.Definition; | |
import org.aspectj.weaver.loadtime.definition.DocumentParser; | |
import org.osgi.framework.Bundle; | |
import org.osgi.framework.wiring.BundleWiring; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
public interface AspectSupport { | |
static Logger logger = LoggerFactory.getLogger(Activator.class); | |
static ClassLoader loader(Bundle bundle) { | |
BundleWiring wiring = bundle.adapt(BundleWiring.class); | |
ClassLoader loader = wiring.getClassLoader(); | |
return loader; | |
} | |
static List<Definition> definitionList(ClassLoader loader, String resource) { | |
Map<URL, Definition> definitionMap = new HashMap<>(); | |
try { | |
Enumeration<URL> resourcezList = loader.getResources(resource); | |
while (resourcezList.hasMoreElements()) { | |
URL url = resourcezList.nextElement(); | |
logger.info("register definition: {}", url); | |
Definition definition = DocumentParser.parse(url); | |
definitionMap.put(url, definition); | |
} | |
return new ArrayList<>(definitionMap.values()); | |
} catch (Exception e) { | |
throw new Error(e); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.carrotgarden.base.osgi_aj; | |
import java.util.concurrent.ConcurrentHashMap; | |
import java.util.concurrent.ConcurrentMap; | |
import org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor; | |
import org.osgi.framework.hooks.weaving.WeavingHook; | |
import org.osgi.framework.hooks.weaving.WovenClass; | |
import org.osgi.framework.wiring.BundleWiring; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
public class AspectWeaver implements WeavingHook { | |
static Logger logger = LoggerFactory.getLogger(AspectWeaver.class); | |
protected ConcurrentMap<ClassLoader, ClassLoaderWeavingAdaptor> adaptorMap = new ConcurrentHashMap<>(); | |
protected ClassLoaderWeavingAdaptor ensureAdaptor(BundleWiring wiring) { | |
ClassLoader key = wiring.getClassLoader(); | |
return adaptorMap.computeIfAbsent(key, loader -> { | |
logger.info("register loader: {}", loader); | |
ClassLoaderWeavingAdaptor adaptor = new ClassLoaderWeavingAdaptor(); | |
AspectContext context = new AspectContext(wiring); | |
adaptor.initialize(loader, context); | |
return adaptor; | |
}); | |
} | |
@Override | |
public void weave(WovenClass woven) { | |
try { | |
String name = woven.getClassName(); | |
BundleWiring wiring = woven.getBundleWiring(); | |
ClassLoaderWeavingAdaptor adaptor = ensureAdaptor(wiring); | |
final byte[] source = woven.getBytes(); | |
final byte[] target; | |
// aspectj is single-threaded | |
synchronized (adaptor) { | |
target = adaptor.weaveClass(name, source); | |
} | |
woven.setBytes(target); | |
if (source != target) { | |
logger.info("woven class: {}", name); | |
} | |
} catch (Throwable e) { | |
throw new Error(e); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
I am so intersted with using AOP on osgi. Can you provide a full example explaining how to use this solution