Package org.eclipse.osgi.internal.loader

Source Code of org.eclipse.osgi.internal.loader.BundleLoaderProxy

/*******************************************************************************
* Copyright (c) 2003, 2008 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:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.internal.loader;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import org.eclipse.osgi.framework.internal.core.*;
import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.util.KeyedHashSet;
import org.eclipse.osgi.framework.util.SecureAction;
import org.eclipse.osgi.internal.composite.CompositeBase;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.ExportPackageDescription;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.RequiredBundle;

/*
* The BundleLoaderProxy proxies a BundleLoader object for a Bundle.  This
* allows for a Bundle's depedencies to be linked without forcing the
* creating of the BundleLoader or BundleClassLoader objects.  This class
* keeps track of the depedencies between the bundles installed in the
* Framework.
*/
public class BundleLoaderProxy implements RequiredBundle {
  static SecureAction secureAction = (SecureAction) AccessController.doPrivileged(SecureAction.createSecureAction());
  // The BundleLoader that this BundleLoaderProxy is managing
  private BundleLoader loader;
  // The Bundle that this BundleLoaderProxy is for
  final private BundleHost bundle;
  // the BundleDescription for the Bundle
  final private BundleDescription description;
  // Indicates if this BundleLoaderProxy is stale;
  // this is true when the bundle is updated or uninstalled.
  private boolean stale = false;
  // cached of package sources for the bundle
  final private KeyedHashSet pkgSources;

  public BundleLoaderProxy(BundleHost bundle, BundleDescription description) {
    this.bundle = bundle;
    this.description = description;
    this.pkgSources = new KeyedHashSet(false);
  }

  public BundleLoader getBundleLoader() {
    if (System.getSecurityManager() == null)
      return getBundleLoader0();
    return (BundleLoader) AccessController.doPrivileged(new PrivilegedAction() {
      public Object run() {
        return getBundleLoader0();
      }
    });
  }

  synchronized BundleLoader getBundleLoader0() {
    if (loader != null)
      return loader;
    if (bundle.isResolved()) {
      try {
        if (bundle.getBundleId() == 0) // this is the system bundle
          loader = new SystemBundleLoader(bundle, this);
        else
          loader = new BundleLoader(bundle, this);
      } catch (BundleException e) {
        bundle.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, e);
        return null;
      }
    }
    return loader;
  }

  public BundleLoader getBasicBundleLoader() {
    return loader;
  }

  public AbstractBundle getBundleHost() {
    return bundle;
  }

  void setStale() {
    stale = true;
  }

  public boolean isStale() {
    return stale;
  }

  public String toString() {
    String symbolicName = bundle.getSymbolicName();
    StringBuffer sb = new StringBuffer(symbolicName == null ? bundle.getBundleData().getLocation() : symbolicName);
    sb.append("; ").append(Constants.BUNDLE_VERSION_ATTRIBUTE); //$NON-NLS-1$
    sb.append("=\"").append(description.getVersion().toString()).append("\""); //$NON-NLS-1$//$NON-NLS-2$
    return sb.toString();
  }

  public org.osgi.framework.Bundle getBundle() {
    if (isStale())
      return null;

    return bundle;
  }

  public org.osgi.framework.Bundle[] getRequiringBundles() {
    if (isStale())
      return null;
    // This is VERY slow; but never gets called in regular execution.
    BundleDescription[] dependents = description.getDependents();
    if (dependents == null || dependents.length == 0)
      return new Bundle[0];
    ArrayList result = new ArrayList(dependents.length);
    for (int i = 0; i < dependents.length; i++)
      addRequirers(dependents[i], result);
    return (Bundle[]) result.toArray(new org.osgi.framework.Bundle[result.size()]);
  }

  void addRequirers(BundleDescription dependent, ArrayList result) {
    if (dependent.getHost() != null) // don't look in fragments.
      return;
    BundleLoaderProxy dependentProxy = getBundleLoader().getLoaderProxy(dependent);
    if (dependentProxy == null)
      return; // bundle must have been uninstalled
    if (result.contains(dependentProxy.bundle))
      return; // prevent endless recusion
    BundleLoader dependentLoader = dependentProxy.getBundleLoader();
    BundleLoaderProxy[] requiredBundles = dependentLoader.requiredBundles;
    int[] reexportTable = dependentLoader.reexportTable;
    if (requiredBundles == null)
      return;
    int size = reexportTable == null ? 0 : reexportTable.length;
    int reexportIndex = 0;
    for (int i = 0; i < requiredBundles.length; i++) {
      if (requiredBundles[i] == this) {
        result.add(dependentProxy.bundle);
        if (reexportIndex < size && reexportTable[reexportIndex] == i) {
          reexportIndex++;
          BundleDescription[] dependents = dependent.getDependents();
          if (dependents == null)
            return;
          for (int j = 0; j < dependents.length; j++)
            dependentProxy.addRequirers(dependents[j], result);
        }
        return;
      }
    }
    return;
  }

  public String getSymbolicName() {
    return description.getSymbolicName();
  }

  public Version getVersion() {
    return description.getVersion();
  }

  public boolean isRemovalPending() {
    return description.isRemovalPending();
  }

  BundleDescription getBundleDescription() {
    return description;
  }

  PackageSource getPackageSource(String pkgName) {
    // getByKey is called outside of a synch block because we really do not
    // care too much of duplicates getting created.  Only the first one will
    // successfully get stored into pkgSources
    PackageSource pkgSource = (PackageSource) pkgSources.getByKey(pkgName);
    if (pkgSource == null) {
      pkgSource = new SingleSourcePackage(pkgName, this);
      synchronized (pkgSources) {
        pkgSources.add(pkgSource);
      }
    }
    return pkgSource;
  }

  public boolean inUse() {
    return (description.getDependents().length > 0) || ((bundle instanceof CompositeBase) && description.getResolvedImports().length > 0);
  }

  boolean forceSourceCreation(ExportPackageDescription export) {
    boolean strict = Constants.STRICT_MODE.equals(secureAction.getProperty(Constants.OSGI_RESOLVER_MODE));
    return (export.getDirective(Constants.INCLUDE_DIRECTIVE) != null) || (export.getDirective(Constants.EXCLUDE_DIRECTIVE) != null) || (strict && export.getDirective(Constants.FRIENDS_DIRECTIVE) != null);
  }

  // creates a PackageSource from an ExportPackageDescription.  This is called when initializing
  // a BundleLoader to ensure that the proper PackageSource gets created and used for
  // filtered and reexport packages.  The storeSource flag is used by initialize to indicate
  // that the source for special case package sources (filtered or re-exported should be stored
  // in the cache.  if this flag is set then a normal SinglePackageSource will not be created
  // (i.e. it will be created lazily)
  public PackageSource createPackageSource(ExportPackageDescription export, boolean storeSource) {
    PackageSource pkgSource = null;

    // check to see if it is a filtered export
    String includes = (String) export.getDirective(Constants.INCLUDE_DIRECTIVE);
    String excludes = (String) export.getDirective(Constants.EXCLUDE_DIRECTIVE);
    String[] friends = (String[]) export.getDirective(Constants.FRIENDS_DIRECTIVE);
    if (friends != null) {
      boolean strict = Constants.STRICT_MODE.equals(secureAction.getProperty(Constants.OSGI_RESOLVER_MODE));
      if (!strict)
        friends = null; // do not pay attention to friends if not in strict mode
    }
    if (includes != null || excludes != null || friends != null) {
      pkgSource = new FilteredSourcePackage(export.getName(), this, includes, excludes, friends);
    }

    if (storeSource) {
      // if the package source is not null then store the source only if it is not already present;
      // getByKey is called outside of a synch block because we really do not
      // care too much of duplicates getting created.  Only the first one will
      // successfully get stored into pkgSources
      if (pkgSource != null && pkgSources.getByKey(export.getName()) == null)
        synchronized (pkgSources) {
          pkgSources.add(pkgSource);
        }
    } else {
      // we are not storing the special case sources, but pkgSource == null this means this
      // is a normal package source; get it and return it.
      if (pkgSource == null) {
        pkgSource = getPackageSource(export.getName());
        // the first export cached may not be a simple single source like we need.
        if (pkgSource.getClass() != SingleSourcePackage.class)
          return new SingleSourcePackage(export.getName(), this);
      }
    }

    return pkgSource;
  }
}
TOP

Related Classes of org.eclipse.osgi.internal.loader.BundleLoaderProxy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.