/******************************************************************************* * Copyright (c) 2006, 2014 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * 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; } public IWeavingAdaptor getAdaptor(final long bundleID) { return this.adaptors.get(bundleID); } 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 (int i = 0; i < installedBundles.length; i++) { if (installedBundles[i].getState() != Bundle.UNINSTALLED) { supplementerRegistry .addSupplementer(installedBundles[i], false); } } for (int i = 0; i < installedBundles.length; i++) { if (installedBundles[i].getState() != Bundle.UNINSTALLED) { supplementerRegistry.addSupplementedBundle(installedBundles[i]); } } 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); } } } 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; } }