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