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
   *
   *      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.apache.camel.k.tooling.maven;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.Writer;
  import java.nio.charset.StandardCharsets;
  import java.nio.file.Files;
  import java.nio.file.Path;
  import java.nio.file.Paths;
  import java.security.NoSuchAlgorithmException;
  import java.util.Collections;
  import java.util.LinkedHashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Objects;
  import java.util.stream.Collectors;
  
  import org.apache.maven.artifact.Artifact;
  import org.apache.maven.artifact.DefaultArtifact;
  import org.apache.maven.plugin.AbstractMojo;
  import org.apache.maven.plugin.MojoExecutionException;
  import org.apache.maven.plugin.MojoFailureException;
  import org.apache.maven.plugins.annotations.LifecyclePhase;
  import org.apache.maven.plugins.annotations.Mojo;
  import org.apache.maven.plugins.annotations.Parameter;
  import org.apache.maven.plugins.annotations.ResolutionScope;
  import org.apache.maven.project.MavenProject;
  import org.yaml.snakeyaml.DumperOptions;
  import org.yaml.snakeyaml.Yaml;
  
  import static org.apache.camel.k.tooling.maven.support.MavenSupport.sha1Hex;
  
  @Mojo(
      name = "generate-dependency-list",
      defaultPhase = LifecyclePhase.PREPARE_PACKAGE,
      threadSafe = true,
      requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
      requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME)
  public class GenerateDependencyListMojo extends AbstractMojo {
      private static final String[] CHECKSUM_TYPES = {"md5", "sha1"};
  
      @Parameter(readonly = true, defaultValue = "${project}")
      private MavenProject project;
  
      @Parameter(property = "dependencies.file", defaultValue = "${project.build.directory}/dependencies.yaml")
      private String outputFile;
  
      @Parameter(defaultValue = "true")
      private boolean includeLocation;
  
      @Override
      public void execute() throws MojoExecutionException, MojoFailureException {
          final Path output = Paths.get(this.outputFile);
  
          try {
              if (Files.notExists(output.getParent())) {
                  Files.createDirectories(output.getParent());
              }
          } catch (IOException e) {
              throw new MojoExecutionException("Exception while generating dependencies list", e);
          }
  
          try (Writer writer = Files.newBufferedWriter(output, StandardCharsets.UTF_8)) {
              List<Map<String, String>> deps = project.getArtifacts().stream()
                  .filter(this::isCompileOrRuntime)
                  .map(this::artifactToMap)
                  .collect(Collectors.toList());
  
              DumperOptions options = new DumperOptions();
              options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
  
              Yaml yaml = new Yaml(options);
              yaml.dump(Collections.singletonMap("dependencies", deps), writer);
          } catch (IOException e) {
              throw new MojoExecutionException("Exception while generating dependencies list", e);
          }
      }
  
      private boolean isCompileOrRuntime(Artifact artifact) {
          return Objects.equals(artifact.getScope(), DefaultArtifact.SCOPE_COMPILE)
              || Objects.equals(artifact.getScope(), DefaultArtifact.SCOPE_RUNTIME);
      }
  
      private Map<String, String> artifactToMap(Artifact artifact) {
          Map<String, String> dep = new LinkedHashMap<>();
          dep.put("id", artifact.getId());
  
          if (artifact.getFile() == null) {
              return dep;
          }
  
          if (includeLocation) {
              dep.put("location", artifact.getFile().getAbsolutePath());
          }
  
          try {
              String location = artifact.getFile().getAbsolutePath();
              String checksum = null;
  
              for (String checksumType : CHECKSUM_TYPES) {
                  Path checksumFile = Paths.get(location + "." + checksumType);
                  if (Files.exists(checksumFile)) {
                      checksum = checksumType + ":" + Files.readString(checksumFile, StandardCharsets.UTF_8);
                      break;
                  }
              }
  
              if (checksum == null) {
                  try (InputStream is = Files.newInputStream(artifact.getFile().toPath())) {
                      checksum = "sha1:" + sha1Hex(is);
                  }
              }
  
              dep.put("checksum", checksum);
          } catch (IOException | NoSuchAlgorithmException e) {
              throw new RuntimeException(e);
          }
  
          return dep;
      }
  }
  