diff options
Diffstat (limited to 'bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/SupplementerRegistry.java')
-rw-r--r-- | bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/SupplementerRegistry.java | 528 |
1 files changed, 297 insertions, 231 deletions
diff --git a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/SupplementerRegistry.java b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/SupplementerRegistry.java index c47ab8e64..425f669c7 100644 --- a/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/SupplementerRegistry.java +++ b/bundles/org.eclipse.equinox.weaving.hook/src/org/eclipse/equinox/service/weaving/SupplementerRegistry.java @@ -8,11 +8,13 @@ * Contributors: * Matthew Webster initial implementation * Martin Lippert supplementing mechanism reworked + * Heiko Seeberger Enhancements for service dynamics *******************************************************************************/ package org.eclipse.equinox.service.weaving; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Dictionary; import java.util.HashMap; @@ -33,236 +35,300 @@ import org.osgi.framework.Constants; import org.osgi.service.packageadmin.PackageAdmin; public class SupplementerRegistry { - - /** - * Manifest header (named "Supplement-Importer") identifying the names - * (and optionally, version numbers) of the packages that the bundle supplements. - * All importers of one of these packages will have the exported packages of this - * bundle added to their imports in addition. - * - * <p> - * The attribute value may be retrieved from the <code>Dictionary</code> - * object returned by the <code>Bundle.getHeaders</code> method. - */ - public static final String SUPPLEMENT_IMPORTER = "Eclipse-SupplementImporter"; //$NON-NLS-1$ - - /** - * Manifest header (named "Supplement-Exporter") identifying the names - * (and optionally, version numbers) of the packages that the bundle supplements. - * All exporters of one of these packages will have the exported packages of this bundle - * added to their imports list. - * - * <p> - * The attribute value may be retrieved from the <code>Dictionary</code> - * object returned by the <code>Bundle.getHeaders</code> method. - */ - public static final String SUPPLEMENT_EXPORTER = "Eclipse-SupplementExporter"; //$NON-NLS-1$ - - //knibb - /** - * Manifest header (named "Supplement-Bundle") identifying the names - * (and optionally, version numbers) of any bundles supplemented by this bundle. - * All supplemented bundles will have all the exported packages of this bundle - * added to their imports list - * - * <p> - * The attribute value may be retrieved from the <code>Dictionary</code> - * object returned by the <code>Bundle.getHeaders</code> method. - */ - public static final String SUPPLEMENT_BUNDLE = "Eclipse-SupplementBundle"; //$NON-NLS-1$ - - private final Map supplementers; // keys of type String (symbolic name of supplementer bundle), values of type Supplementer - private final Set dontWeaveTheseBundles; // elements of type String (symbolic name of bundle) - private BundleContext context; - private PackageAdmin packageAdmin; - - public SupplementerRegistry() { - this.supplementers = new HashMap(); - this.dontWeaveTheseBundles = new HashSet(); - - this.dontWeaveTheseBundles.add("org.eclipse.osgi"); - this.dontWeaveTheseBundles.add("org.eclipse.update.configurator"); - this.dontWeaveTheseBundles.add("org.eclipse.core.runtime"); - this.dontWeaveTheseBundles.add("org.eclipse.equinox.common"); - this.dontWeaveTheseBundles.add("org.eclipse.equinox.weaving.hook"); - this.dontWeaveTheseBundles.add("org.eclipse.equinox.weaving.aspectj"); - this.dontWeaveTheseBundles.add("org.eclipse.equinox.weaving.caching"); - this.dontWeaveTheseBundles.add("org.eclipse.equinox.weaving.caching.j9"); - this.dontWeaveTheseBundles.add("org.aspectj.runtime"); - this.dontWeaveTheseBundles.add("org.aspectj.weaver"); - this.dontWeaveTheseBundles.add("org.eclipse.equinox.simpleconfigurator"); - } - - public void setBundleContext(BundleContext context) { - this.context = context; - } - - public void setPackageAdmin(PackageAdmin packageAdmin) { - this.packageAdmin = packageAdmin; - } - - public void addSupplementer(Bundle bundle) { - Dictionary manifest = bundle.getHeaders(); - try { - // First analyze which supplementers already exists for this bundle - ManifestElement[] imports = ManifestElement.parseHeader(Constants.IMPORT_PACKAGE, (String) manifest.get(Constants.IMPORT_PACKAGE)); - ManifestElement[] exports = ManifestElement.parseHeader(Constants.EXPORT_PACKAGE, (String) manifest.get(Constants.EXPORT_PACKAGE)); - List supplementers = getSupplementers(bundle.getSymbolicName(), imports, exports); - if (supplementers.size() > 0) { - this.addSupplementedBundle(bundle, supplementers); - } - - // Second analyze if this bundle itself is a supplementer - ManifestElement[] supplementBundle = ManifestElement.parseHeader(SUPPLEMENT_BUNDLE, (String) manifest.get(SUPPLEMENT_BUNDLE)); - ManifestElement[] supplementImporter = ManifestElement.parseHeader(SUPPLEMENT_IMPORTER, (String) manifest.get(SUPPLEMENT_IMPORTER)); - ManifestElement[] supplementExporter = ManifestElement.parseHeader(SUPPLEMENT_EXPORTER, (String) manifest.get(SUPPLEMENT_EXPORTER)); - - if (supplementBundle != null || supplementImporter != null || supplementExporter != null) { - Supplementer newSupplementer = new Supplementer(bundle, supplementBundle, supplementImporter, supplementExporter); - - this.supplementers.put(bundle.getSymbolicName(), newSupplementer); - resupplementInstalledBundles(newSupplementer); - } - } - catch (BundleException e) { - } - } - - public void removeSupplementer(Bundle bundle) { - // if this bundle is itself supplemented by others, remove the bundle from those lists - removeSupplementedBundle(bundle); - - // if this bundle supplements other bundles, remove this supplementer and update the other bundles - if (supplementers.containsKey(bundle.getSymbolicName())) { - Supplementer supplementer = (Supplementer) supplementers.get(bundle.getSymbolicName()); - supplementers.remove(bundle.getSymbolicName()); - if (AbstractAspectJHook.verbose) System.err.println("[org.aspectj.osgi] info removing supplementer " + bundle.getSymbolicName()); - - Bundle[] supplementedBundles = supplementer.getSupplementedBundles(); - for (int i = 0; i < supplementedBundles.length; i++) { - Bundle supplementedBundle = supplementedBundles[i]; - if (supplementedBundle != null) { - updateInstalledBundle(supplementedBundle); - } - } - } - } - - public List getSupplementers (String symbolicName, ManifestElement[] imports, ManifestElement[] exports) { - List result = Collections.EMPTY_LIST; - - if (supplementers.size() > 0 && !this.dontWeaveTheseBundles.contains(symbolicName)) { - result = new LinkedList(); - for (Iterator i = supplementers.values().iterator(); i.hasNext();) { - Supplementer supplementer = (Supplementer) i.next(); - if (isSupplementerMatching(symbolicName, imports, exports, supplementer)) { - result.add(supplementer.getSymbolicName()); - } - } - } - - return result; - } - - public Bundle[] getSupplementers(Bundle bundle) { - List result = Collections.EMPTY_LIST; - - if (supplementers.size() > 0) { - result = new ArrayList(); - for (Iterator i = supplementers.values().iterator(); i.hasNext();) { - Supplementer supplementer = (Supplementer) i.next(); - if (supplementer.isSupplemented(bundle)) { - result.add(supplementer.getSupplementerBundle()); - } - } - } - - return (Bundle[]) result.toArray(new Bundle[result.size()]); - } - - public void addSupplementedBundle(Bundle supplementedBundle, List supplementers) { - for (Iterator iterator = supplementers.iterator(); iterator.hasNext();) { - String supplementersName = (String) iterator.next(); - if (this.supplementers.containsKey(supplementersName)) { - Supplementer supplementer = (Supplementer) this.supplementers.get(supplementersName); - supplementer.addSupplementedBundle(supplementedBundle); - } - } - } - - public void removeSupplementedBundle(Bundle bundle) { - for (Iterator iterator = this.supplementers.values().iterator(); iterator.hasNext();) { - Supplementer supplementer = (Supplementer) iterator.next(); - supplementer.removeSupplementedBundle(bundle); - } - } - - private boolean isSupplementerMatching(String symbolicName, - ManifestElement[] imports, ManifestElement[] exports, Supplementer supplementer) { - String supplementerName = supplementer.getSymbolicName(); - if (!supplementerName.equals(symbolicName)) { - if (supplementer.matchSupplementer(symbolicName) - || (imports != null && supplementer.matchesSupplementImporter(imports)) - || (exports != null && supplementer.matchesSupplementExporter(exports))) { - return true; - } - } - return false; - } - - private void resupplementInstalledBundles(Supplementer supplementer) { - Bundle[] installedBundles = context.getBundles(); - - for (int i = 0; i < installedBundles.length; i++) { - try { - Bundle bundle = installedBundles[i]; - - if (bundle.getSymbolicName().equals(supplementer.getSymbolicName())) { - continue; - } - - if (dontWeaveTheseBundles.contains(bundle.getSymbolicName())) { - continue; - } - - Dictionary manifest = bundle.getHeaders(); - ManifestElement[] imports = ManifestElement.parseHeader(Constants.IMPORT_PACKAGE, (String) manifest.get(Constants.IMPORT_PACKAGE)); - ManifestElement[] exports = ManifestElement.parseHeader(Constants.EXPORT_PACKAGE, (String) manifest.get(Constants.EXPORT_PACKAGE)); - - if (isSupplementerMatching(bundle.getSymbolicName(), imports, exports, supplementer)) { - boolean alreadyRequired = false; - ManifestElement[] requires = ManifestElement.parseHeader(Constants.REQUIRE_BUNDLE, (String) manifest.get(Constants.REQUIRE_BUNDLE)); - if (requires != null) { - for (int j = 0; j < requires.length; j++) { - if (requires[j].getValue().equals(supplementer.getSymbolicName())) { - alreadyRequired = true; - } - } - } - - if (!alreadyRequired) { - updateInstalledBundle(bundle); - } - } - - } catch (BundleException e) { - e.printStackTrace(); - } - } - } - - private void updateInstalledBundle(Bundle bundle) { - if (AbstractAspectJHook.verbose) System.err.println("[org.aspectj.osgi] info triggering update for re-supplementing " + bundle.getSymbolicName()); - - try { - int initialstate = (bundle.getState() | (Bundle.ACTIVE | Bundle.STARTING)); - if (initialstate != 0 && packageAdmin != null && packageAdmin.getBundleType(bundle) != PackageAdmin.BUNDLE_TYPE_FRAGMENT) - bundle.stop(Bundle.STOP_TRANSIENT); - bundle.update(); - } - catch (BundleException e) { - e.printStackTrace(); - } - } + + //knibb + /** + * Manifest header (named "Supplement-Bundle") identifying the + * names (and optionally, version numbers) of any bundles supplemented by + * this bundle. All supplemented bundles will have all the exported packages + * of this bundle added to their imports list + * + * <p> + * The attribute value may be retrieved from the <code>Dictionary</code> + * object returned by the <code>Bundle.getHeaders</code> method. + */ + public static final String SUPPLEMENT_BUNDLE = "Eclipse-SupplementBundle"; //$NON-NLS-1$ + + /** + * Manifest header (named "Supplement-Exporter") identifying the + * names (and optionally, version numbers) of the packages that the bundle + * supplements. All exporters of one of these packages will have the + * exported packages of this bundle added to their imports list. + * + * <p> + * The attribute value may be retrieved from the <code>Dictionary</code> + * object returned by the <code>Bundle.getHeaders</code> method. + */ + public static final String SUPPLEMENT_EXPORTER = "Eclipse-SupplementExporter"; //$NON-NLS-1$ + + /** + * Manifest header (named "Supplement-Importer") identifying the + * names (and optionally, version numbers) of the packages that the bundle + * supplements. All importers of one of these packages will have the + * exported packages of this bundle added to their imports in addition. + * + * <p> + * The attribute value may be retrieved from the <code>Dictionary</code> + * object returned by the <code>Bundle.getHeaders</code> method. + */ + public static final String SUPPLEMENT_IMPORTER = "Eclipse-SupplementImporter"; //$NON-NLS-1$ + + private BundleContext context; + + private final Set dontWeaveTheseBundles; // elements of type String (symbolic name of bundle) + + private PackageAdmin packageAdmin; + + private final Map supplementers; // keys of type String (symbolic name of supplementer bundle), values of type Supplementer + + public SupplementerRegistry() { + this.supplementers = new HashMap(); + this.dontWeaveTheseBundles = new HashSet(); + + this.dontWeaveTheseBundles.add("org.eclipse.osgi"); + this.dontWeaveTheseBundles.add("org.eclipse.update.configurator"); + this.dontWeaveTheseBundles.add("org.eclipse.core.runtime"); + this.dontWeaveTheseBundles.add("org.eclipse.equinox.common"); + this.dontWeaveTheseBundles.add("org.eclipse.equinox.weaving.hook"); + this.dontWeaveTheseBundles.add("org.eclipse.equinox.weaving.aspectj"); + this.dontWeaveTheseBundles.add("org.eclipse.equinox.weaving.caching"); + this.dontWeaveTheseBundles + .add("org.eclipse.equinox.weaving.caching.j9"); + this.dontWeaveTheseBundles.add("org.aspectj.runtime"); + this.dontWeaveTheseBundles.add("org.aspectj.weaver"); + this.dontWeaveTheseBundles + .add("org.eclipse.equinox.simpleconfigurator"); + } + + public void addSupplementedBundle(final Bundle supplementedBundle, + final List supplementers) { + for (final Iterator iterator = supplementers.iterator(); iterator + .hasNext();) { + final String supplementersName = (String) iterator.next(); + if (this.supplementers.containsKey(supplementersName)) { + final Supplementer supplementer = (Supplementer) this.supplementers + .get(supplementersName); + supplementer.addSupplementedBundle(supplementedBundle); + } + } + } + + public void addSupplementer(final Bundle bundle) { + final Dictionary manifest = bundle.getHeaders(); + try { + // First analyze which supplementers already exists for this bundle + final ManifestElement[] imports = ManifestElement.parseHeader( + Constants.IMPORT_PACKAGE, (String) manifest + .get(Constants.IMPORT_PACKAGE)); + final ManifestElement[] exports = ManifestElement.parseHeader( + Constants.EXPORT_PACKAGE, (String) manifest + .get(Constants.EXPORT_PACKAGE)); + final List supplementers = getSupplementers(bundle + .getSymbolicName(), imports, exports); + if (supplementers.size() > 0) { + this.addSupplementedBundle(bundle, supplementers); + } + + // Second analyze if this bundle itself is a supplementer + final ManifestElement[] supplementBundle = ManifestElement + .parseHeader(SUPPLEMENT_BUNDLE, (String) manifest + .get(SUPPLEMENT_BUNDLE)); + final ManifestElement[] supplementImporter = ManifestElement + .parseHeader(SUPPLEMENT_IMPORTER, (String) manifest + .get(SUPPLEMENT_IMPORTER)); + final ManifestElement[] supplementExporter = ManifestElement + .parseHeader(SUPPLEMENT_EXPORTER, (String) manifest + .get(SUPPLEMENT_EXPORTER)); + + if (supplementBundle != null || supplementImporter != null + || supplementExporter != null) { + final Supplementer newSupplementer = new Supplementer(bundle, + supplementBundle, supplementImporter, + supplementExporter); + + this.supplementers.put(bundle.getSymbolicName(), + newSupplementer); + resupplementInstalledBundles(newSupplementer); + } + } catch (final BundleException e) { + } + } + + public Set getSupplementedBundles() { + final Set supplementedBundles = new HashSet(); + final Iterator supplementersIterator = supplementers.values() + .iterator(); + while (supplementersIterator.hasNext()) { + final Supplementer supplementer = (Supplementer) supplementersIterator + .next(); + supplementedBundles.addAll(Arrays.asList(supplementer + .getSupplementedBundles())); + } + return supplementedBundles; + } + + public Bundle[] getSupplementers(final Bundle bundle) { + List result = Collections.EMPTY_LIST; + + if (supplementers.size() > 0) { + result = new ArrayList(); + for (final Iterator i = supplementers.values().iterator(); i + .hasNext();) { + final Supplementer supplementer = (Supplementer) i.next(); + if (supplementer.isSupplemented(bundle)) { + result.add(supplementer.getSupplementerBundle()); + } + } + } + + return (Bundle[]) result.toArray(new Bundle[result.size()]); + } + + public List getSupplementers(final String symbolicName, + final ManifestElement[] imports, final ManifestElement[] exports) { + List result = Collections.EMPTY_LIST; + + if (supplementers.size() > 0 + && !this.dontWeaveTheseBundles.contains(symbolicName)) { + result = new LinkedList(); + for (final Iterator i = supplementers.values().iterator(); i + .hasNext();) { + final Supplementer supplementer = (Supplementer) i.next(); + if (isSupplementerMatching(symbolicName, imports, exports, + supplementer)) { + result.add(supplementer.getSymbolicName()); + } + } + } + + return result; + } + + public void removeSupplementedBundle(final Bundle bundle) { + for (final Iterator iterator = this.supplementers.values().iterator(); iterator + .hasNext();) { + final Supplementer supplementer = (Supplementer) iterator.next(); + supplementer.removeSupplementedBundle(bundle); + } + } + + public void removeSupplementer(final Bundle bundle) { + // if this bundle is itself supplemented by others, remove the bundle from those lists + removeSupplementedBundle(bundle); + + // if this bundle supplements other bundles, remove this supplementer and update the other bundles + if (supplementers.containsKey(bundle.getSymbolicName())) { + final Supplementer supplementer = (Supplementer) supplementers + .get(bundle.getSymbolicName()); + supplementers.remove(bundle.getSymbolicName()); + if (AbstractAspectJHook.verbose) + System.err + .println("[org.aspectj.osgi] info removing supplementer " + + bundle.getSymbolicName()); + + final Bundle[] supplementedBundles = supplementer + .getSupplementedBundles(); + for (int i = 0; i < supplementedBundles.length; i++) { + final Bundle supplementedBundle = supplementedBundles[i]; + if (supplementedBundle != null) { + updateInstalledBundle(supplementedBundle); + } + } + } + } + + public void setBundleContext(final BundleContext context) { + this.context = context; + } + + public void setPackageAdmin(final PackageAdmin packageAdmin) { + this.packageAdmin = packageAdmin; + } + + public void updateInstalledBundle(final Bundle bundle) { + if (AbstractAspectJHook.verbose) + System.err + .println("[org.aspectj.osgi] info triggering update for re-supplementing " + + bundle.getSymbolicName()); + + try { + final int initialstate = (bundle.getState() | (Bundle.ACTIVE | Bundle.STARTING)); + // TODO Why stop? Shouldn't start again? + if (initialstate != 0 + && packageAdmin != null + && packageAdmin.getBundleType(bundle) != PackageAdmin.BUNDLE_TYPE_FRAGMENT) + bundle.stop(Bundle.STOP_TRANSIENT); + bundle.update(); + } catch (final BundleException e) { + e.printStackTrace(); + } + } + + private boolean isSupplementerMatching(final String symbolicName, + final ManifestElement[] imports, final ManifestElement[] exports, + final Supplementer supplementer) { + final String supplementerName = supplementer.getSymbolicName(); + if (!supplementerName.equals(symbolicName)) { + if (supplementer.matchSupplementer(symbolicName) + || (imports != null && supplementer + .matchesSupplementImporter(imports)) + || (exports != null && supplementer + .matchesSupplementExporter(exports))) { + return true; + } + } + return false; + } + + private void resupplementInstalledBundles(final Supplementer supplementer) { + final Bundle[] installedBundles = context.getBundles(); + + for (int i = 0; i < installedBundles.length; i++) { + try { + final Bundle bundle = installedBundles[i]; + + if (bundle.getSymbolicName().equals( + supplementer.getSymbolicName())) { + continue; + } + + if (dontWeaveTheseBundles.contains(bundle.getSymbolicName())) { + continue; + } + + final Dictionary manifest = bundle.getHeaders(); + final ManifestElement[] imports = ManifestElement.parseHeader( + Constants.IMPORT_PACKAGE, (String) manifest + .get(Constants.IMPORT_PACKAGE)); + final ManifestElement[] exports = ManifestElement.parseHeader( + Constants.EXPORT_PACKAGE, (String) manifest + .get(Constants.EXPORT_PACKAGE)); + + if (isSupplementerMatching(bundle.getSymbolicName(), imports, + exports, supplementer)) { + boolean alreadyRequired = false; + final ManifestElement[] requires = ManifestElement + .parseHeader(Constants.REQUIRE_BUNDLE, + (String) manifest + .get(Constants.REQUIRE_BUNDLE)); + if (requires != null) { + for (int j = 0; j < requires.length; j++) { + if (requires[j].getValue().equals( + supplementer.getSymbolicName())) { + alreadyRequired = true; + } + } + } + + if (!alreadyRequired) { + updateInstalledBundle(bundle); + } + } + + } catch (final BundleException e) { + e.printStackTrace(); + } + } + } } |