Skip to content

Instantly share code, notes, and snippets.

@Andrei-Pozolotin
Created May 9, 2018 18:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Andrei-Pozolotin/1c3b9da1bb6d1edbbcea22471520dc07 to your computer and use it in GitHub Desktop.
Save Andrei-Pozolotin/1c3b9da1bb6d1edbbcea22471520dc07 to your computer and use it in GitHub Desktop.
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());
}
}
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;
}
}
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);
}
}
}
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);
}
}
}
@babdenbi
Copy link

Hi,

I am so intersted with using AOP on osgi. Can you provide a full example explaining how to use this solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment