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.core.install;
  
  import java.io.File;
  import java.io.IOException;
  import java.util.Arrays;
  import java.util.Date;
  
  import org.apache.ivy.core.cache.ArtifactOrigin;
  import org.apache.ivy.core.module.descriptor.Configuration;
  import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
  import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
  import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
  import org.apache.ivy.core.module.id.ModuleId;
  import org.apache.ivy.core.module.id.ModuleRevisionId;
  import org.apache.ivy.core.report.ArtifactDownloadReport;
  import org.apache.ivy.core.report.MetadataArtifactDownloadReport;
  import org.apache.ivy.core.report.ResolveReport;
  import org.apache.ivy.core.resolve.DownloadOptions;
  import org.apache.ivy.core.resolve.IvyNode;
  import org.apache.ivy.core.resolve.ResolveEngine;
  import org.apache.ivy.core.resolve.ResolveOptions;
  import org.apache.ivy.core.search.SearchEngine;
  import org.apache.ivy.plugins.conflict.NoConflictManager;
  import org.apache.ivy.plugins.matcher.ExactPatternMatcher;
  import org.apache.ivy.plugins.matcher.MatcherHelper;
  import org.apache.ivy.plugins.matcher.PatternMatcher;
  import org.apache.ivy.plugins.resolver.DependencyResolver;
  import org.apache.ivy.util.Message;
  
  public class InstallEngine {
      private InstallEngineSettings settings;
  
      private ResolveEngine resolveEngine;
  
      private SearchEngine searchEngine;
  
      public InstallEngine(InstallEngineSettings settings, SearchEngine searchEngine,
              ResolveEngine resolveEngine) {
          this.settings = settings;
          this.searchEngine = searchEngine;
          this.resolveEngine = resolveEngine;
      }
  
      public ResolveReport install(ModuleRevisionId mrid, String from, String to,
              InstallOptions options) throws IOException {
          DependencyResolver fromResolver = settings.getResolver(from);
          DependencyResolver toResolver = settings.getResolver(to);
          if (fromResolver == null) {
              throw new IllegalArgumentException("unknown resolver " + from
                      + ". Available resolvers are: " + settings.getResolverNames());
          }
          if (toResolver == null) {
              throw new IllegalArgumentException("unknown resolver " + to
                      + ". Available resolvers are: " + settings.getResolverNames());
          }
          PatternMatcher matcher = settings.getMatcher(options.getMatcherName());
          if (matcher == null) {
              throw new IllegalArgumentException("unknown matcher " + options.getMatcherName()
                      + ". Available matchers are: " + settings.getMatcherNames());
          }
  
          // build module file declaring the dependency
          Message.info(":: installing " + mrid + " ::");
          DependencyResolver oldDictator = resolveEngine.getDictatorResolver();
          boolean log = settings.logNotConvertedExclusionRule();
          try {
              settings.setLogNotConvertedExclusionRule(true);
              resolveEngine.setDictatorResolver(fromResolver);
  
              DefaultModuleDescriptor md = new DefaultModuleDescriptor(ModuleRevisionId.newInstance(
                  "apache", "ivy-install", "1.0"), settings.getStatusManager().getDefaultStatus(),
                      new Date());
              String resolveId = ResolveOptions.getDefaultResolveId(md);
              md.addConfiguration(new Configuration("default"));
              md.addConflictManager(new ModuleId(ExactPatternMatcher.ANY_EXPRESSION,
                      ExactPatternMatcher.ANY_EXPRESSION), ExactPatternMatcher.INSTANCE,
                  new NoConflictManager());
  
              for (String dc : options.getConfs()) {
                  final String depConf = dc.trim();
  
                  if (MatcherHelper.isExact(matcher, mrid)) {
                      DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(md, mrid,
                              false, false, options.isTransitive());
                      dd.addDependencyConfiguration("default", depConf);
                      md.addDependency(dd);
                  } else {
                      for (ModuleRevisionId imrid : searchEngine.listModules(fromResolver, mrid, matcher)) {
                          Message.info("\tfound " + imrid + " to install: adding to the list");
                          DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(md,
                                  imrid, false, false, options.isTransitive());
                          dd.addDependencyConfiguration("default", depConf);
                          md.addDependency(dd);
                      }
                  }
              }
  
              // resolve using appropriate resolver
              ResolveReport report = new ResolveReport(md, resolveId);
  
              Message.info(":: resolving dependencies ::");
              ResolveOptions resolveOptions = new ResolveOptions().setResolveId(resolveId)
                      .setConfs(new String[] {"default"}).setValidate(options.isValidate());
              IvyNode[] dependencies = resolveEngine.getDependencies(md, resolveOptions, report);
              report.setDependencies(Arrays.asList(dependencies), options.getArtifactFilter());
  
              Message.info(":: downloading artifacts to cache ::");
              resolveEngine.downloadArtifacts(report, options.getArtifactFilter(),
                  new DownloadOptions());
  
              // now that everything is in cache, we can publish all these modules
              Message.info(":: installing in " + to + " ::");
              for (IvyNode dependency : dependencies) {
                  ModuleDescriptor depmd = dependency.getDescriptor();
                  if (depmd != null) {
                      ModuleRevisionId depMrid = depmd.getModuleRevisionId();
                      Message.verbose("installing " + depMrid);
                      boolean successfullyPublished = false;
                      try {
                          toResolver.beginPublishTransaction(depMrid, options.isOverwrite());
  
                          // publish artifacts
                          for (ArtifactDownloadReport artifact : report.getArtifactsReports(depMrid)) {
                              if (artifact.getLocalFile() != null) {
                                  toResolver.publish(artifact.getArtifact(), artifact.getLocalFile(),
                                      options.isOverwrite());
                              }
                          }
  
                          // publish metadata
                          MetadataArtifactDownloadReport artifactDownloadReport = dependency
                                  .getModuleRevision().getReport();
                          File localIvyFile = artifactDownloadReport.getLocalFile();
                          toResolver.publish(depmd.getMetadataArtifact(), localIvyFile,
                              options.isOverwrite());
  
                          if (options.isInstallOriginalMetadata()) {
                              if (artifactDownloadReport.getArtifactOrigin() != null
                                      && artifactDownloadReport.getArtifactOrigin().isExists()
                                      && !ArtifactOrigin.isUnknown(artifactDownloadReport
                                              .getArtifactOrigin())
                                      && artifactDownloadReport.getArtifactOrigin().getArtifact() != null
                                      && artifactDownloadReport.getArtifactOrigin().getArtifact()
                                              .getType().endsWith(".original")
                                      && !artifactDownloadReport
                                              .getArtifactOrigin()
                                              .getArtifact()
                                              .getType()
                                              .equals(
                                                  depmd.getMetadataArtifact().getType() + ".original")) {
                                  // publish original metadata artifact, too, as it has a different
                                  // type
                                  toResolver.publish(artifactDownloadReport.getArtifactOrigin()
                                          .getArtifact(), artifactDownloadReport
                                          .getOriginalLocalFile(), options.isOverwrite());
                              }
                          }
  
                          // end module publish
                          toResolver.commitPublishTransaction();
                          successfullyPublished = true;
                      } finally {
                          if (!successfullyPublished) {
                              toResolver.abortPublishTransaction();
                          }
                      }
                  }
              }
  
              Message.info(":: install resolution report ::");
  
              // output report
              resolveEngine
                      .outputReport(report, settings.getResolutionCacheManager(), resolveOptions);
  
              return report;
          } finally {
              // IVY-834: log the problems if there were any...
              Message.sumupProblems();
  
              resolveEngine.setDictatorResolver(oldDictator);
              settings.setLogNotConvertedExclusionRule(log);
          }
      }
  
  }
  