package com.yoursway.osgi.javaflow; import java.io.IOException; import java.net.URLConnection; import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Properties; import org.apache.commons.javaflow.bytecode.transformation.ResourceTransformer; import org.eclipse.osgi.baseadaptor.BaseAdaptor; import org.eclipse.osgi.baseadaptor.BaseData; import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry; import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook; import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook; import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader; import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry; import org.eclipse.osgi.baseadaptor.loader.ClasspathManager; import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain; import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate; import org.eclipse.osgi.framework.log.FrameworkLog; import org.eclipse.osgi.internal.loader.BundleLoader; import org.eclipse.osgi.util.ManifestElement; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.Constants; public class InstrumentationHook implements AdaptorHook, ClassLoadingHook { private static final String MANIFEST_KEY = "JavaFlow-Enabled"; private final ResourceTransformer transformer; public InstrumentationHook(ResourceTransformer transformer) { if (transformer == null) throw new NullPointerException("transformer is null"); this.transformer = transformer; } public void frameworkStart(BundleContext context) throws BundleException { } public void frameworkStop(BundleContext context) throws BundleException { } public byte[] processClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) { try { Object value = manager.getBaseData().getManifest().get(MANIFEST_KEY); if (value instanceof String && Boolean.parseBoolean((String) value)) { System.out.println("Instrumenting with Javaflow: " + name); return transformer.transform(classbytes); } } catch (BundleException e) { e.printStackTrace(); } return null; } public BaseClassLoader createClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, BundleProtectionDomain domain, BaseData data, String[] bundleclasspath) { BundleLoader loader = (BundleLoader) delegate; try { loader.addDynamicImportPackage(ManifestElement.parseHeader(Constants.DYNAMICIMPORT_PACKAGE, "org.apache.bcel,org.apache.bcel.classfile,org.apache.bcel.generic,"+ "org.apache.bcel.util,org.apache.bcel.verifier,org.apache.bcel.verifier.exc,"+ "org.apache.bcel.verifier.statics,org.apache.bcel.verifier.structurals,"+ "org.apache.commons.javaflow,org.apache.commons.javaflow.ant,org.apache.commons.javaflow.bytecode," + "org.apache.commons.javaflow.bytecode.transformation,"+ "org.apache.commons.javaflow.bytecode.transformation.asm,"+ "org.apache.commons.javaflow.bytecode.transformation.bcel,"+ "org.apache.commons.javaflow.bytecode.transformation.bcel.analyser," + "org.apache.commons.javaflow.stores," + "org.apache.commons.javaflow.utils," + "org.apache.commons.logging," + "org.apache.commons.logging.impl")); } catch (BundleException be) { throw new RuntimeException(be); } return null; } // Methods stubs for hooks we do not require: @SuppressWarnings("unchecked") public boolean addClassPathEntry(ArrayList cpEntries, String cp, ClasspathManager hostmanager, BaseData sourcedata, ProtectionDomain sourcedomain) { return false; } public String findLibrary(BaseData data, String libName) { return null; } public ClassLoader getBundleClassLoaderParent() { return null; } public void initializedClassLoader(BaseClassLoader baseClassLoader, BaseData data) { } public void addProperties(Properties properties) { } public FrameworkLog createFrameworkLog() { return null; } public void frameworkStopping(BundleContext context) { } public void handleRuntimeError(Throwable error) { } public void initialize(BaseAdaptor adaptor) { } public URLConnection mapLocationToURLConnection(String location) throws IOException { return null; } public boolean matchDNChain(String pattern, String[] dnChain) { return false; } }