@Override
  public Iterator<Resource> iterateResources(String startPath, boolean recursive) {

    // Collect paths for substituted packages
    List<String> importedPaths = new ArrayList<String>();
    BundleWiring wiring = hostRev.getBundle().adapt(BundleWiring.class);
    List<BundleRequirement> preqs =
        wiring != null ? wiring.getRequirements(PackageNamespace.PACKAGE_NAMESPACE) : null;
    if (preqs != null) {
      for (BundleRequirement req : preqs) {
        XPackageRequirement preq = (XPackageRequirement) req;
        String packageName = preq.getPackageName();
        importedPaths.add(packageName.replace('.', '/'));
      }
    }
    Iterator<Resource> itres = delegate.iterateResources(startPath, recursive);
    if (importedPaths.isEmpty()) {
      return itres;
    }

    // Filter substituted packages
    List<Resource> filteredResources = new ArrayList<Resource>();
    while (itres.hasNext()) {
      Resource res = itres.next();
      String pathname = res.getName();
      int lastIndex = pathname.lastIndexOf('/');
      String respath = lastIndex > 0 ? pathname.substring(0, lastIndex) : pathname;
      if (!importedPaths.contains(respath)) {
        filteredResources.add(res);
      }
    }

    return filteredResources.iterator();
  }
 FallbackLoader(
     HostBundleRevision hostRev, ModuleIdentifier identifier, Set<String> importedPaths) {
   if (hostRev == null) throw new IllegalArgumentException("Null hostRev");
   if (identifier == null) throw new IllegalArgumentException("Null identifier");
   if (importedPaths == null) throw new IllegalArgumentException("Null importedPaths");
   this.identifier = identifier;
   this.importedPaths = importedPaths;
   this.hostRev = hostRev;
   this.hostBundle = hostRev.getBundleState();
   this.bundleManager = hostBundle.getBundleManager();
   this.moduleManager = hostBundle.getFrameworkState().getModuleManagerPlugin();
 }
  @Override
  public URL getLocalizationEntry(String path) {

    URL result = null;

    // #Bug1867 - Finding Localization Entries for Fragments
    // https://www.osgi.org/members/bugzilla/show_bug.cgi?id=1867
    boolean fallbackToFragment = true;

    // If the bundle is a resolved fragment, then the search for localization data must
    // delegate to the attached host bundle with the highest version.
    if (getWiring() != null) {
      HostBundleRevision highest = null;
      for (HostBundleRevision hostrev : getAttachedHosts()) {
        if (highest == null) highest = hostrev;
        if (highest.getVersion().compareTo(hostrev.getVersion()) < 0) highest = hostrev;
      }
      if (highest == null)
        throw FrameworkMessages.MESSAGES.illegalStateCannotObtainAttachedHost(this);

      boolean hostUninstalled = highest.getBundleState().isUninstalled();
      result = (hostUninstalled ? getEntry(path) : highest.getLocalizationEntry(path));

      // In contrary to the spec the TCK ManifestLocalizationTests.testGetHeaders010()
      // expects to find the localization files in the fragment if they were not found
      // in the attached host
      if (result != null || fallbackToFragment == false) return result;
    }

    // If the fragment is not resolved, then the framework must search the fragment's JAR for the
    // localization entry.
    result = getEntry(path);
    return result;
  }
  void attachToHost(HostBundleRevision hostRev) {
    if (attachedHosts == null) attachedHosts = new HashSet<HostBundleRevision>();

    hostRev.attachFragment(this);
    attachedHosts.add(hostRev);
  }