Package org.springframework.osgi.io.internal.resolver

Source Code of org.springframework.osgi.io.internal.resolver.PackageAdminResolver

/*
* Copyright 2006-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.osgi.io.internal.resolver;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
import org.springframework.osgi.io.internal.OsgiHeaderUtils;
import org.springframework.util.Assert;

/**
* {@link PackageAdmin} based dependency resolver.
*
* <p/> This implementation uses the OSGi PackageAdmin service to determine
* dependencies between bundles. Since it's highly dependent on an external
* service, it might be better to use a listener based implementation for
* non-performant environments.
*
* <p/> This implementation does consider required bundles.
*
* @author Costin Leau
*
*/
public class PackageAdminResolver implements DependencyResolver {

  private final BundleContext bundleContext;


  public PackageAdminResolver(BundleContext bundleContext) {
    Assert.notNull(bundleContext);
    this.bundleContext = bundleContext;
  }

  public ImportedBundle[] getImportedBundles(Bundle bundle) {
    PackageAdmin pa = getPackageAdmin();

    // create map with bundles as keys and a list of packages as value
    Map importedBundles = new LinkedHashMap(8);

    // 1. consider required bundles first

    // see if there are required bundle(s) defined
    String[] entries = OsgiHeaderUtils.getRequireBundle(bundle);

    // 1. if so, locate the bundles
    for (int i = 0; i < entries.length; i++) {
      String[] parsed = OsgiHeaderUtils.parseRequiredBundleString(entries[i]);
      Bundle requiredBundle = pa.getBundles(parsed[0], parsed[1])[0];

      // find exported packages
      ExportedPackage[] exportedPackages = pa.getExportedPackages(requiredBundle);
      if (exportedPackages != null)
        addExportedPackages(importedBundles, requiredBundle, exportedPackages);
    }

    // 2. determine imported bundles
    // get all bundles
    Bundle[] bundles = bundleContext.getBundles();

    for (int i = 0; i < bundles.length; i++) {
      Bundle analyzedBundle = bundles[i];
      // if the bundle is already included (it's a required one), there's no need to look at it again
      if (!importedBundles.containsKey(analyzedBundle)) {
        ExportedPackage[] epa = pa.getExportedPackages(analyzedBundle);
        if (epa != null)
          for (int j = 0; j < epa.length; j++) {
            ExportedPackage exportedPackage = epa[j];
            Bundle[] importingBundles = exportedPackage.getImportingBundles();
            if (importingBundles != null)
              for (int k = 0; k < importingBundles.length; k++) {
                if (bundle.equals(importingBundles[k])) {
                  addImportedBundle(importedBundles, exportedPackage.getExportingBundle(),
                    exportedPackage.getName());
                }
              }
          }
      }
    }

    List importedBundlesList = new ArrayList(importedBundles.size());

    for (Iterator iterator = importedBundles.entrySet().iterator(); iterator.hasNext();) {
      Map.Entry entry = (Map.Entry) iterator.next();
      Bundle importedBundle = (Bundle) entry.getKey();
      List packages = (List) entry.getValue();
      importedBundlesList.add(new ImportedBundle(importedBundle,
        (String[]) packages.toArray(new String[packages.size()])));
    }

    return (ImportedBundle[]) importedBundlesList.toArray(new ImportedBundle[importedBundlesList.size()]);
  }

  /**
   * Adds the imported bundles to the map of packages.
   *
   * @param map
   * @param bundle
   * @param packageName
   */
  private void addImportedBundle(Map map, Bundle bundle, String packageName) {
    List packages = (List) map.get(bundle);
    if (packages == null) {
      packages = new ArrayList(4);
      map.put(bundle, packages);
    }
    packages.add(packageName);
  }

  /**
   * Adds the bundle exporting the given packages which are then imported by
   * the owning bundle. This applies to special imports (such as
   * Require-Bundle).
   *
   * @param map
   * @param bundle
   * @param pkgs
   */
  private void addExportedPackages(Map map, Bundle bundle, ExportedPackage[] pkgs) {
    List packages = (List) map.get(bundle);
    if (packages == null) {
      packages = new ArrayList(pkgs.length);
      map.put(bundle, packages);
    }
    for (int i = 0; i < pkgs.length; i++) {
      ExportedPackage exportedPackage = pkgs[i];
      packages.add(exportedPackage.getName());
    }
  }

  private PackageAdmin getPackageAdmin() {
    ServiceReference ref = bundleContext.getServiceReference(PackageAdmin.class.getName());
    if (ref == null)
      throw new IllegalStateException(PackageAdmin.class.getName() + " service is required");
    // don't do any proxying since PackageAdmin is normally a framework service
    // we can assume for now that it will stay
    return (PackageAdmin) bundleContext.getService(ref);
  }
};
TOP

Related Classes of org.springframework.osgi.io.internal.resolver.PackageAdminResolver

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.