/******************************************************************************* * Copyright (c) 2008, 2010 VMware Inc. * 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: * VMware Inc. - initial contribution *******************************************************************************/ package org.eclipse.virgo.kernel.userregion.internal.quasi; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.equinox.region.Region; import org.eclipse.osgi.baseadaptor.BaseData; import org.eclipse.osgi.framework.adaptor.BundleData; import org.eclipse.osgi.framework.internal.core.BundleHost; import org.eclipse.osgi.service.resolver.BundleDescription; import org.eclipse.osgi.service.resolver.BundleSpecification; import org.eclipse.osgi.service.resolver.ExportPackageDescription; import org.eclipse.osgi.service.resolver.HostSpecification; import org.eclipse.osgi.service.resolver.ImportPackageSpecification; import org.osgi.framework.Bundle; import org.osgi.framework.BundleException; import org.osgi.framework.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.eclipse.virgo.kernel.artifact.plan.PlanDescriptor.Provisioning; import org.eclipse.virgo.kernel.osgi.quasi.QuasiBundle; import org.eclipse.virgo.kernel.osgi.quasi.QuasiExportPackage; import org.eclipse.virgo.kernel.osgi.quasi.QuasiImportPackage; import org.eclipse.virgo.kernel.osgi.quasi.QuasiRequiredBundle; import org.eclipse.virgo.util.osgi.manifest.BundleManifest; /** * {@link StandardQuasiBundle} is the default implementation of {@link QuasiBundle}. * <p /> * * <strong>Concurrent Semantics</strong><br /> * * This class is thread safe. * */ final class StandardQuasiBundle implements QuasiBundle { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final BundleDescription bundleDescription; private final BundleManifest bundleManifest; private volatile Bundle bundle = null; private final String bsn; private Version bv; private final Region region; private volatile Provisioning provisioning = Provisioning.AUTO; /** * Constructs an unresolved, uncommitted {@link QuasiBundle} with the given {@link BundleDescription}. * * @param bundleDescription the <code>BundleDescription</code> for this <code>QuasiBundle</code> * @param bundleManifest * @param region the <code>Region</code> this bundle belongs to */ public StandardQuasiBundle(BundleDescription bundleDescription, BundleManifest bundleManifest, Region region) { this.bundleDescription = bundleDescription; this.bundleManifest = bundleManifest; this.region = region; this.bsn = bundleDescription.getSymbolicName(); this.bv = bundleDescription.getVersion(); } BundleDescription getBundleDescription() { return this.bundleDescription; } BundleManifest getBundleManifest() { return this.bundleManifest; } /** * {@inheritDoc} */ public String getSymbolicName() { return this.bundleDescription.getSymbolicName(); } /** * {@inheritDoc} */ public Version getVersion() { return this.bundleDescription.getVersion(); } /** * {@inheritDoc} */ public boolean isResolved() { return this.bundleDescription.isResolved(); } /** * {@inheritDoc} * @throws BundleException */ public void uninstall() { Bundle bundle = this.getBundle(); this.bundle = null; if(bundle != null){ this.region.removeBundle(bundle); try { bundle.uninstall(); } catch (BundleException e) { this.logger.error("Uninstall of '{}' failed", e, this); } } } public void setBundle(Bundle bundle) { this.bundle = bundle; } /** * {@inheritDoc} */ public Bundle getBundle() { if(this.bundle == null){ return this.region.getBundle(this.bsn, this.bv); } return this.bundle; } /** * {@inheritDoc} */ public long getBundleId() { return this.bundleDescription.getBundleId(); } /** * {@inheritDoc} */ public String getBundleLocation() { Bundle bundle = this.getBundle(); if(bundle == null){ return this.bundleDescription.getLocation(); } return bundle.getLocation(); } /** * {@inheritDoc} */ public Region getRegion() { return this.region; } /** * {@inheritDoc} */ public List<QuasiBundle> getFragments() { BundleDescription[] fragments = this.bundleDescription.getFragments(); return this.wrapBundleDescriptions(fragments); } /** * {@inheritDoc} */ public List<QuasiBundle> getHosts() { HostSpecification hostSpecification = this.bundleDescription.getHost(); return hostSpecification == null ? null : this.wrapBundleDescriptions(hostSpecification.getHosts()); } /** * {@inheritDoc} */ public List<QuasiExportPackage> getExportPackages() { ExportPackageDescription[] exportPackages = this.bundleDescription.getExportPackages(); return this.wrapExportPackageDescriptions(exportPackages); } /** * {@inheritDoc} */ public List<QuasiImportPackage> getImportPackages() { return this.wrapImportPackageSpecifications(this.bundleDescription.getImportPackages()); } /** * {@inheritDoc} */ public List<QuasiRequiredBundle> getRequiredBundles() { return this.wrapBundleSpecificationsAsRequiredBundles(this.bundleDescription.getRequiredBundles()); } /** * {@inheritDoc} */ public List<QuasiBundle> getDependents() { BundleDescription[] dependents = this.bundleDescription.getDependents(); return this.wrapBundleDescriptions(dependents); } /** * Utility method to wrap a list of {@link BundleDescription} in QuasiBundle. * * @param bundleDescriptions * @return */ private List<QuasiBundle> wrapBundleDescriptions(BundleDescription[] bundleDescriptions) { List<QuasiBundle> quasiBundles = new ArrayList<QuasiBundle>(); for (BundleDescription bundleDescription : bundleDescriptions) { Region bundleRegion = this.region.getRegionDigraph().getRegion(bundleDescription.getBundleId()); quasiBundles.add(new StandardQuasiBundle(bundleDescription, null, bundleRegion)); } return Collections.unmodifiableList(quasiBundles); } /** * Utility method to wrap a list of {@link BundleDescription} in QuasiBundle. * * @param bundleDescriptions * @return */ private List<QuasiRequiredBundle> wrapBundleSpecificationsAsRequiredBundles(BundleSpecification[] bundleDescriptions) { List<QuasiRequiredBundle> quasiRequiredBundles = new ArrayList<QuasiRequiredBundle>(); for (BundleSpecification bundleSpecification : bundleDescriptions) { quasiRequiredBundles.add(new StandardQuasiRequiredBundle(bundleSpecification, this)); } return Collections.unmodifiableList(quasiRequiredBundles); } /** * Utility method to wrap a list of {@link BundleDescription} in {@link QuasiExportPackage}. * * @param exportPackageDescriptions * @param quasiBundle * @return */ private List<QuasiExportPackage> wrapExportPackageDescriptions(ExportPackageDescription[] exportPackageDescriptions) { List<QuasiExportPackage> quasiExportPackages = new ArrayList<QuasiExportPackage>(); for (ExportPackageDescription exportPackageDescription : exportPackageDescriptions) { quasiExportPackages.add(new StandardQuasiExportPackage(exportPackageDescription, this)); } return Collections.unmodifiableList(quasiExportPackages); } /** * Utility method to wrap a list of {@link BundleDescription} in {@link QuasiImportPackage}. * * @param bundleDescriptions * @return */ private List<QuasiImportPackage> wrapImportPackageSpecifications(ImportPackageSpecification[] importPackageSpecifications) { List<QuasiImportPackage> quasiImportPackages = new ArrayList<QuasiImportPackage>(); for (ImportPackageSpecification importPackageSpecification : importPackageSpecifications) { quasiImportPackages.add(new StandardQuasiImportPackage(importPackageSpecification, this)); } return Collections.unmodifiableList(quasiImportPackages); } /** * {@inheritDoc} */ @Override public String toString() { return "QuasiBundle(" + getRegion().getName() + "[" + getSymbolicName() + ", " + getVersion() + "])"; } /** * {@inheritDoc} */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((bsn == null) ? 0 : bsn.hashCode()); result = prime * result + ((bv == null) ? 0 : bv.hashCode()); return result; } /** * {@inheritDoc} */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; StandardQuasiBundle other = (StandardQuasiBundle) obj; if (bsn == null) { if (other.bsn != null) return false; } else if (!bsn.equals(other.bsn)) return false; if (bv == null) { if (other.bv != null) return false; } else if (!bv.equals(other.bv)) return false; return true; } public File getBundleFile() { if (bundle instanceof BundleHost) { BundleHost bh = (BundleHost) bundle; BundleData bundleData = bh.getBundleData(); if (bundleData instanceof BaseData) { File file = ((BaseData) bundleData).getBundleFile().getBaseFile(); return file; } } return null; } /** * {@inheritDoc} */ @Override public void setProvisioning(Provisioning provisioning) { if (provisioning == null) { throw new IllegalArgumentException("null not a valid provisioning behaviour for a QuasiBundle"); } if (provisioning == Provisioning.INHERIT) { throw new IllegalArgumentException("INHERIT is not a valid provisioning behaviour for a QuasiBundle"); } this.provisioning = provisioning; } /** * {@inheritDoc} */ @Override public Provisioning getProvisioning() { return this.provisioning; } }