content: /*
   *  Licensed to the Apache Software Foundation (ASF) under one or more
   *  contributor license agreements.  See the NOTICE file distributed with
   *  this work for additional information regarding copyright ownership.
   *  The ASF licenses this file to You 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
   *
   *      https://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.apache.ivy.osgi.repo;
  
  import java.io.IOException;
  import java.net.URI;
  import java.text.ParseException;
  import java.util.Iterator;
  import java.util.NoSuchElementException;
  import java.util.jar.JarInputStream;
  import java.util.jar.Manifest;
  
  import org.apache.ivy.core.event.EventManager;
  import org.apache.ivy.core.module.descriptor.Artifact;
  import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
  import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
  import org.apache.ivy.core.module.id.ModuleRevisionId;
  import org.apache.ivy.core.resolve.ResolveData;
  import org.apache.ivy.core.resolve.ResolveEngine;
  import org.apache.ivy.core.resolve.ResolveOptions;
  import org.apache.ivy.core.resolve.ResolvedModuleRevision;
  import org.apache.ivy.core.search.ModuleEntry;
  import org.apache.ivy.core.search.OrganisationEntry;
  import org.apache.ivy.core.search.RevisionEntry;
  import org.apache.ivy.core.settings.IvySettings;
  import org.apache.ivy.core.sort.SortEngine;
  import org.apache.ivy.osgi.core.BundleInfoAdapter;
  import org.apache.ivy.plugins.resolver.BasicResolver;
  import org.apache.ivy.plugins.resolver.util.ResolvedResource;
  import org.apache.ivy.util.Message;
  
  public class ResolverManifestIterable implements Iterable<ManifestAndLocation> {
  
      // We should support the interface DependencyResolver, but the API is not convenient to get
      // references to artifact
      private final BasicResolver resolver;
  
      public ResolverManifestIterable(BasicResolver resolver) {
          this.resolver = resolver;
      }
  
      public Iterator<ManifestAndLocation> iterator() {
          return new ResolverManifestIterator();
      }
  
      class ResolverManifestIterator implements Iterator<ManifestAndLocation> {
  
          private OrganisationEntry[] organisations;
  
          private int indexOrganisation = 0;
  
          private OrganisationEntry organisation;
  
          private ModuleEntry[] modules;
  
          private int indexModule = -1;
  
          private ModuleEntry module;
  
          private ManifestAndLocation next = null;
  
          private RevisionEntry[] revisions;
  
          private int indexRevision;
  
          private RevisionEntry revision;
  
          private Artifact[] artifacts;
  
          private int indexArtifact;
  
          private Artifact artifact;
  
          private ModuleRevisionId mrid;
  
          private ResolveData data;
  
          public ResolverManifestIterator() {
              organisations = resolver.listOrganisations();
              IvySettings settings = new IvySettings();
              ResolveEngine engine = new ResolveEngine(settings, new EventManager(), new SortEngine(
                      settings));
              data = new ResolveData(engine, new ResolveOptions());
          }
  
          public boolean hasNext() {
              while (next == null) {
                  if (organisation == null) {
                      if (indexOrganisation >= organisations.length) {
                          return false;
                      }
                      organisation = organisations[indexOrganisation++];
                      modules = resolver.listModules(organisation);
                      indexModule = 0;
                      module = null;
                  }
                  if (module == null) {
                      if (indexModule >= modules.length) {
                          organisation = null;
                          continue;
                      }
                      module = modules[indexModule++];
                      revisions = resolver.listRevisions(module);
                      indexRevision = 0;
                      revision = null;
                  }
                  if (revision == null) {
                      if (indexRevision >= revisions.length) {
                          module = null;
                          continue;
                      }
                      revision = revisions[indexRevision++];
                      mrid = ModuleRevisionId.newInstance(organisation.getOrganisation(),
                          module.getModule(), revision.getRevision());
                      DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(mrid, false);
                      ResolvedModuleRevision dependency;
                      try {
                          dependency = resolver.getDependency(dd, data);
                      } catch (ParseException e) {
                          Message.error("Error while resolving " + mrid + " : " + e.getMessage());
                          revision = null;
                          continue;
                      }
                      if (dependency == null) {
                          revision = null;
                          continue;
                      }
                      ModuleDescriptor md = dependency.getDescriptor();
                      mrid = md.getModuleRevisionId();
                      artifacts = md.getAllArtifacts();
                      indexArtifact = 0;
                      artifact = null;
                  }
                  if (artifact == null) {
                      if (indexArtifact >= artifacts.length) {
                          revision = null;
                          continue;
                      }
                      artifact = artifacts[indexArtifact++];
                  }
                  ResolvedResource resource = resolver.doFindArtifactRef(artifact, null);
                  if (resource == null) {
                      artifact = null;
                      continue;
                  }
                  JarInputStream in;
                  try {
                      in = new JarInputStream(resource.getResource().openStream());
                  } catch (IOException e) {
                      Message.warn("Unreadable jar " + resource.getResource().getName() + " ("
                              + e.getMessage() + ")");
                      artifact = null;
                      continue;
                  }
                  Manifest manifest;
                  try {
                      manifest = in.getManifest();
                  } finally {
                      try {
                          in.close();
                      } catch (IOException e) {
                          // don't care
                      }
                  }
                  if (manifest == null) {
                      Message.debug("No manifest on " + artifact);
                  } else {
                      URI uri = BundleInfoAdapter.buildIvyURI(artifact);
                      next = new ManifestAndLocation(manifest, uri, null);
                  }
                  artifact = null;
              }
              return true;
          }
  
          public ManifestAndLocation next() {
              if (!hasNext()) {
                  throw new NoSuchElementException();
              }
              ManifestAndLocation manifest = next;
              next = null;
              return manifest;
          }
  
          public void remove() {
              throw new UnsupportedOperationException();
          }
      }
  
  }
  