blob: ca45ea2d13814f47e5d9c583c7c638e608ef302c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2014 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* David Knibb initial implementation
* Matthew Webster Eclipse 3.2 changes
* Martin Lippert supplementing mechanism reworked
*******************************************************************************/
package org.eclipse.equinox.weaving.hooks;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.equinox.service.weaving.ISupplementerRegistry;
import org.eclipse.equinox.weaving.adaptors.Debug;
import org.eclipse.equinox.weaving.adaptors.IWeavingAdaptor;
import org.eclipse.equinox.weaving.adaptors.WeavingAdaptor;
import org.eclipse.equinox.weaving.adaptors.WeavingAdaptorFactory;
import org.eclipse.osgi.internal.loader.ModuleClassLoader;
import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry;
import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.packageadmin.PackageAdmin;
public class WeavingHook extends AbstractWeavingHook {
private final WeavingAdaptorFactory adaptorFactory;
private final Map<Long, IWeavingAdaptor> adaptors;
private BundleContext bundleContext;
public WeavingHook() {
if (Debug.DEBUG_GENERAL) Debug.println("- WeavingHook.<init>()");
this.adaptorFactory = new WeavingAdaptorFactory();
this.adaptors = new HashMap<Long, IWeavingAdaptor>();
}
@Override
public void classLoaderCreated(final ModuleClassLoader classLoader) {
if (Debug.DEBUG_GENERAL)
Debug.println("> WeavingHook.initializedClassLoader() bundle="
+ classLoader.getBundle().getSymbolicName()
+ ", loader="
+ classLoader
+ ", bundleFile="
+ classLoader.getClasspathManager().getGeneration()
.getBundleFile());
final IWeavingAdaptor adaptor = createWeavingAdaptor(classLoader
.getClasspathManager().getGeneration(), classLoader);
this.adaptors.put(classLoader.getBundle().getBundleId(), adaptor);
if (Debug.DEBUG_GENERAL)
Debug.println("< WeavingHook.initializedClassLoader() adaptor="
+ adaptor);
}
private IWeavingAdaptor createWeavingAdaptor(final Generation generation,
final ModuleClassLoader classLoader) {
if (Debug.DEBUG_GENERAL)
Debug.println("> WeavingHook.createAspectJAdaptor() location="
+ generation.getRevision().getRevisions().getModule()
.getLocation());
IWeavingAdaptor adaptor = null;
if (adaptorFactory != null) {
adaptor = new WeavingAdaptor(generation, adaptorFactory, null,
null, classLoader);
} else {
if (Debug.DEBUG_GENERAL)
Debug.println("- WeavingHook.createAspectJAdaptor() factory="
+ adaptorFactory);
}
if (Debug.DEBUG_GENERAL)
Debug.println("< WeavingHook.createAspectJAdaptor() adaptor="
+ adaptor);
return adaptor;
}
@Override
public IWeavingAdaptor getAdaptor(final long bundleID) {
return this.adaptors.get(bundleID);
}
@Override
public IWeavingAdaptor getHostBundleAdaptor(final long bundleID) {
final Bundle bundle = this.bundleContext.getBundle(bundleID);
if (bundle != null) {
final Bundle host = adaptorFactory.getHost(bundle);
if (host != null) {
final long hostBundleID = host.getBundleId();
return this.adaptors.get(hostBundleID);
}
}
return null;
}
private void initialize(final BundleContext context) {
if (Debug.DEBUG_GENERAL)
Debug.println("> WeavingHook.initialize() context=" + context);
this.bundleContext = context;
final ISupplementerRegistry supplementerRegistry = getSupplementerRegistry();
adaptorFactory.initialize(context, supplementerRegistry);
final ServiceReference<PackageAdmin> serviceReference = context
.getServiceReference(PackageAdmin.class);
final PackageAdmin packageAdmin = context.getService(serviceReference);
supplementerRegistry.setBundleContext(context);
supplementerRegistry.setPackageAdmin(packageAdmin);
context.addBundleListener(new SupplementBundleListener(
supplementerRegistry));
// re-build supplementer registry state for installed bundles
final Bundle[] installedBundles = context.getBundles();
for (Bundle installedBundle : installedBundles) {
if (installedBundle.getState() != Bundle.UNINSTALLED) {
supplementerRegistry.addSupplementer(installedBundle, false);
}
}
for (Bundle installedBundle : installedBundles) {
if (installedBundle.getState() != Bundle.UNINSTALLED) {
supplementerRegistry.addSupplementedBundle(installedBundle);
}
}
if (Debug.DEBUG_GENERAL)
Debug.println("< WeavingHook.initialize() adaptorFactory="
+ adaptorFactory);
}
/**
* @see org.eclipse.equinox.weaving.hooks.AbstractWeavingHook#processClass(java.lang.String,
* byte[], org.eclipse.osgi.baseadaptor.loader.ClasspathEntry,
* org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry,
* org.eclipse.osgi.baseadaptor.loader.ClasspathManager)
*/
@Override
public byte[] processClass(final String name, final byte[] classbytes,
final ClasspathEntry classpathEntry, final BundleEntry entry,
final ClasspathManager manager) {
byte[] newClassytes = null;
if (entry instanceof WeavingBundleEntry) {
final WeavingBundleEntry ajBundleEntry = (WeavingBundleEntry) entry;
if (!ajBundleEntry.dontWeave()) {
final IWeavingAdaptor adaptor = ajBundleEntry.getAdaptor();
newClassytes = adaptor.weaveClass(name, classbytes);
}
}
return newClassytes;
}
/**
* @see org.eclipse.equinox.weaving.hooks.AbstractWeavingHook#recordClassDefine(java.lang.String,
* java.lang.Class, byte[],
* org.eclipse.osgi.baseadaptor.loader.ClasspathEntry,
* org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry,
* org.eclipse.osgi.baseadaptor.loader.ClasspathManager)
*/
@Override
public void recordClassDefine(final String name, final Class<?> clazz,
final byte[] classbytes, final ClasspathEntry classpathEntry,
final BundleEntry entry, final ClasspathManager manager) {
if (clazz == null) {
if (Debug.DEBUG_GENERAL) {
Debug.println("Error in defining class: " + name); //$NON-NLS-1$
}
return;
}
if (entry instanceof WeavingBundleEntry) {
final WeavingBundleEntry ajBundleEntry = (WeavingBundleEntry) entry;
if (!ajBundleEntry.dontWeave()) {
final IWeavingAdaptor adaptor = ajBundleEntry.getAdaptor();
final URL sourceFileURL = ajBundleEntry.getBundleFileURL();
adaptor.storeClass(name, sourceFileURL, clazz, classbytes);
}
}
}
@Override
public void resetAdaptor(final long bundleID) {
this.adaptors.remove(bundleID);
}
/**
* @see org.eclipse.equinox.weaving.hooks.AbstractWeavingHook#frameworkStart(org.osgi.framework.BundleContext)
*/
public void start(final BundleContext context) throws BundleException {
initialize(context);
}
/**
* @see org.eclipse.equinox.weaving.hooks.AbstractWeavingHook#frameworkStop(org.osgi.framework.BundleContext)
*/
public void stop(final BundleContext context) throws BundleException {
adaptorFactory.dispose(context);
}
/**
* @see org.eclipse.osgi.internal.hookregistry.BundleFileWrapperFactoryHook#wrapBundleFile(org.eclipse.osgi.storage.bundlefile.BundleFile,
* org.eclipse.osgi.storage.BundleInfo.Generation, boolean)
*/
public BundleFileWrapper wrapBundleFile(final BundleFile bundleFile,
final Generation generation, final boolean base) {
BundleFileWrapper wrapped = null;
if (Debug.DEBUG_BUNDLE)
Debug.println("> WeavingHook.wrapBundleFile() bundle="
+ (generation.getRevision() != null ? generation
.getRevision().getSymbolicName() : generation
.getBundleInfo().getBundleId()) + " bundleFile="
+ bundleFile + ", generation=" + generation + ", base="
+ base + ", baseFile=" + bundleFile.getBaseFile());
if (base) {
wrapped = new BaseWeavingBundleFile(new BundleAdaptorProvider(
generation, this), bundleFile);
} else {
wrapped = new WeavingBundleFile(new BundleAdaptorProvider(
generation, this), bundleFile);
}
if (Debug.DEBUG_BUNDLE)
Debug.println("< WeavingHook.wrapBundleFile() wrapped=" + wrapped);
return wrapped;
}
}