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;
}
}