/**
   * Register the p-units of a given bundle.
   *
   * @param b the bundle the p-units are in
   */
  public void registerPersistenceUnitsInBundle(Bundle b) {

    debug("Extender.registerPersistenceUnitsInBundle: ", b);
    if (!isAssigned(b)) {
      warning("Register called on bundle " + b.getSymbolicName(), " but bundle was not assigned");
      return;
    }
    if (areCompatibleBundles(b, mgr.getBundle())) {
      debug("Extender provider compatible with bundle: ", b);

      mgr.registerPersistenceUnits(unitsByBundle.get(b));

    } else {
      warning(
          "Cannot support bundle "
              + b.getSymbolicName()
              + " because it is not JPA-compatible with the EclipseLink bundles. "
              + "This is because there are multiple bundles exporting javax.persistence "
              + "and the persistence unit bundle has resolved to a different one than "
              + "the EclipseLink bundles. "
              + "\nTo fix this, uninstall one of the bundles containing javax.persistence "
              + "so that both the persistence unit bundle and the provider bundles resolve "
              + "to the same javax.persistence package.");
      unassignPersistenceUnitsInBundle(b);
      // No point in updating or refreshing.
      // It would likely just re-resolve to the same JPA interface package.
    }
  }
  /**
   * Go through the p-units in a given bundle and assign the ones that do not have a provider, or
   * have a provider specified as this one.
   *
   * @param b the bundle to look for p-units in
   */
  public void tryAssigningPersistenceUnitsInBundle(Bundle b) {

    debug("Extender.tryAssigningPersistenceUnitsInBundle: ", b);
    // If we have already assigned it then bail
    if (isAssigned(b)) {
      warning("Attempted to assign a bundle that was already assigned: ", b.toString());
      return;
    }

    // Look for all of the persistence descriptor files in the bundle
    List<PersistenceDescriptorInfo> descriptorInfos = bundleUtil.persistenceDescriptorInfos(b);

    if (descriptorInfos.isEmpty()) {
      // There were no descriptors specified in the manifest - check if there is any config from
      // config admin
      PersistenceUnitConfiguration config =
          mgr.getConfigAdminListener().configForBundle(b.getSymbolicName());
      if (config != null) {
        // There is a config to go with this bundle.
        // Create a special descriptorInfo with the descriptor string right inside it
        debug("No persistence descriptors, but found a config for bundle ", b);
        descriptorInfos.add(new InlinedDescriptorInfo(config));
      } else {
        // We can't assign it just yet. Add to the limbo list
        warning("No persistence descriptors found in persistence bundle ", b.getSymbolicName());
        debug("Putting bundle ", b, " in limbo");
        inLimbo.put(b.getSymbolicName(), b);
        // The bundle will be removed from being in limbo by the config admin listener when
        // a config comes along that contains the bsn of this bundle. It will then be refreshed.
        return;
      }
    }

    // Do a partial parse of the descriptors
    Set<PUnitInfo> pUnitInfos = bundleUtil.persistenceUnitInfoFromXmlFiles(descriptorInfos);

    // Cycle through each p-unit info and see if a provider was specified
    for (PUnitInfo info : pUnitInfos) {
      if ((info.getProvider() == null)
          || (EclipseLinkProvider.ECLIPSELINK_PROVIDER_CLASS_NAME.equals(info.getProvider()))) {
        // We can be the provider; claim the p-unit and add it to our list
        info.setBundle(b);
        info.setAssignedProvider(mgr.getProvider());
        debug("Assigning punit ", info.getUnitName(), " to this provider");
        addToBundleUnits(unitsByBundle, b, info);
      }
    }
    // If we found any that were for us then move on to do the preResolve work
    List<PUnitInfo> unitsFound = unitsByBundle.get(b);
    if ((unitsFound != null) && (unitsFound.size() != 0)) {
      mgr.preResolve(b, unitsByBundle.get(b));
    }
  }
 @Override
 public void start(BundleContext context) throws Exception {
   debug("Gemini JPA starting...");
   mgr = new GeminiManager();
   mgr.startup(context);
   debug("Gemini JPA started");
 }
  /**
   * Unregister the p-units of a given bundle.
   *
   * @param b the bundle the p-units are in
   */
  public void unregisterPersistenceUnitsInBundle(Bundle b) {

    debug("Extender.unregisterPersistenceUnitsInBundle: ", b);
    if (!isAssigned(b)) {
      warning("Unregister called on bundle " + b.getSymbolicName(), " but bundle was not assigned");
      return;
    }
    mgr.unregisterPersistenceUnits(unitsByBundle.get(b));
  }
  /** Look for persistence unit bundles that were already installed when we came along. */
  public void lookForExistingBundles() {

    // Look at the bundles that are already installed
    Bundle[] installedBundles = mgr.getBundleContext().getBundles();
    debug("Extender.lookForExistingBundles: ", installedBundles);

    // Check if any are p-unit bundles
    for (Bundle b : installedBundles) {
      if (isPersistenceUnitBundle(b)) {
        // We found a persistence unit bundle.
        if (GeminiSystemProperties.refreshPersistenceBundles()) {
          // If bundle is active then refresh it and push it through the life cycle again
          // so it will go through resolving and we can assign it a provider, etc.
          //  if ((b.getState() != Bundle.INSTALLED) && (b.getState() != Bundle.UNINSTALLED)) {
          if (b.getState() == Bundle.ACTIVE) {
            if (isAssigned(b)) {
              debug(
                  "Found existing installed bundle " + b.getSymbolicName(),
                  " but it was already assigned");
            } else {
              debug(
                  "Found active bundle ",
                  b,
                  " - refreshing to push it back to resolve for processing");
              refreshBundle(b);
            }
          }
        } else {
          // Refreshing is disabled - go through assigning and registering process w/o events
          if (b.getState() != Bundle.UNINSTALLED) {
            // Assign the p-unit
            // NOTE: With no refresh, assigning may be happening after the bundle has been resolved
            warning(
                "Extender - Refreshing disabled - entities in bundle " + b.getSymbolicName(),
                " may not be woven");
            tryAssigningPersistenceUnitsInBundle(b);
            // Now if bundle is starting or active then register the p-units in it
            if ((b.getState() == Bundle.STARTING) || (b.getState() == Bundle.ACTIVE)) {
              registerPersistenceUnitsInBundle(b);
            } // Otherwise just let future events take their course
          }
        }
      }
    }
  }
  /**
   * Refresh the persistence bundle. If persistence units have already been registered they should
   * have been unregistered before making this refresh call.
   *
   * @param b the bundle the p-units are in
   */
  public void refreshBundle(Bundle b) {
    debug("Extender.refreshBundle: ", b);

    // Add the list of currently refreshing bundles.
    // (It will be removed when the UNRESOLVED event is fired on it)
    addToRefreshingBundles(b);

    // Call refresh on all of the packages
    PackageAdmin admin = getPackageAdmin(mgr.getBundleContext());
    admin.refreshPackages(new Bundle[] {b});

    /* New 4.3 code to use to refresh bundle */
    /*
    Bundle systemBundle = mgr.getBundleContext().getBundle(0);
    FrameworkWiring fw = systemBundle.adapt(FrameworkWiring.class);
    fw.refreshBundles(Arrays.asList(b));
    */
  }
 @Override
 public void stop(BundleContext context) throws Exception {
   debug("Gemini JPA stopping...");
   mgr.shutdown(context);
   debug("Gemini JPA stopped");
 }
 /** Stop listening to bundle events. */
 public void stopListening() {
   debug("Extender.stopListening");
   mgr.getBundleContext().removeBundleListener(this);
 }
 /** Start listening for bundle events to indicate the presence of persistence unit bundles. */
 public void startListening() {
   debug("Extender.startListening");
   mgr.getBundleContext().addBundleListener(this);
 }