All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.cloud.tools.jib.gradle.extension.quarkus.JibQuarkusExtension Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2020 Google LLC.
 *
 * Licensed 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 com.google.cloud.tools.jib.gradle.extension.quarkus;

import com.google.cloud.tools.jib.api.JavaContainerBuilder;
import com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath;
import com.google.cloud.tools.jib.api.buildplan.ContainerBuildPlan;
import com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer;
import com.google.cloud.tools.jib.gradle.JibExtension;
import com.google.cloud.tools.jib.gradle.extension.GradleData;
import com.google.cloud.tools.jib.gradle.extension.JibGradlePluginExtension;
import com.google.cloud.tools.jib.gradle.extension.quarkus.resolvers.JarResolver;
import com.google.cloud.tools.jib.gradle.extension.quarkus.resolvers.JarResolverFactory;
import com.google.cloud.tools.jib.gradle.extension.quarkus.resolvers.impl.LegacyJarResolver;
import com.google.cloud.tools.jib.plugins.extension.ExtensionLogger;
import com.google.cloud.tools.jib.plugins.extension.ExtensionLogger.LogLevel;
import com.google.cloud.tools.jib.plugins.extension.JibPluginExtensionException;
import com.google.common.base.Strings;
import com.google.common.base.Verify;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.gradle.api.Project;
import org.gradle.api.artifacts.ResolvedArtifact;
import org.gradle.api.artifacts.component.ProjectComponentIdentifier;
import org.gradle.api.plugins.JavaPlugin;

public class JibQuarkusExtension implements JibGradlePluginExtension {

  private AbsoluteUnixPath appRoot = AbsoluteUnixPath.get("/app");
  private List jvmFlags = Collections.emptyList();

  private JarResolver jarResolver = new LegacyJarResolver();
  private PackageType packageType = PackageType.LEGACY;

  @Override
  public Optional> getExtraConfigType() {
    return Optional.empty();
  }

  @Override
  public ContainerBuildPlan extendContainerBuildPlan(
      ContainerBuildPlan buildPlan,
      Map properties,
      Optional config,
      GradleData gradleData,
      ExtensionLogger logger)
      throws JibPluginExtensionException {
    try {
      logger.log(LogLevel.LIFECYCLE, "Running Quarkus Jib extension");

      packageType =
          PackageType.getPackageTypeByName(properties.getOrDefault("packageType", "legacy-jar"));

      readJibConfigurations(gradleData.getProject());

      Project project = gradleData.getProject();
      Path jar = jarResolver.getPathToLocalJar(project);

      ContainerBuildPlan.Builder planBuilder = buildPlan.toBuilder();
      planBuilder.setLayers(Collections.emptyList());

      // Dependency layers
      for (Path path : jarResolver.getPathsToDependencies(project)) {
        addDependencyLayers(project, planBuilder, path);
      }

      // Quarkus JAR layer
      AbsoluteUnixPath appRootJar = jarResolver.getPathToJarInContainer(appRoot);

      FileEntriesLayer jarLayer =
          FileEntriesLayer.builder().setName("quarkus jar").addEntry(jar, appRootJar).build();
      planBuilder.addLayer(jarLayer);

      // Preserve extra directories layers
      String extraFilesLayerName = JavaContainerBuilder.LayerType.EXTRA_FILES.getName();
      buildPlan.getLayers().stream()
          .filter(layer -> layer.getName().startsWith(extraFilesLayerName))
          .forEach(planBuilder::addLayer);

      // Set entrypoint
      List entrypoint = new ArrayList<>();
      entrypoint.add("java");
      entrypoint.addAll(jvmFlags);
      entrypoint.add("-jar");
      entrypoint.add(appRootJar.toString());
      planBuilder.setEntrypoint(entrypoint);

      return planBuilder.build();

    } catch (IOException ex) {
      throw new JibPluginExtensionException(getClass(), Verify.verifyNotNull(ex.getMessage()), ex);
    }
  }

  private void addDependencyLayers(
      Project project, ContainerBuildPlan.Builder planBuilder, Path libDirectory)
      throws IOException {
    List projectDependencyFilenames =
        project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME)
            .getResolvedConfiguration().getResolvedArtifacts().stream()
            .filter(
                artifact ->
                    artifact.getId().getComponentIdentifier() instanceof ProjectComponentIdentifier)
            .map(ResolvedArtifact::getFile)
            .map(File::getName)
            .collect(Collectors.toList());

    Predicate isProjectDependency =
        path ->
            projectDependencyFilenames.stream()
                // endsWith: Quarkus prepends group ID to the augmented JARs in target/lib.
                .anyMatch(jarFilename -> path.getFileName().toString().endsWith(jarFilename));
    Predicate isSnapshot =
        path ->
            path.getFileName().toString().contains("SNAPSHOT") && !isProjectDependency.test(path);
    Predicate isThirdParty = isProjectDependency.negate().and(isSnapshot.negate());

    addDependencyLayer(project, planBuilder, libDirectory, "dependencies", isThirdParty);
    addDependencyLayer(project, planBuilder, libDirectory, "snapshot dependencies", isSnapshot);
    addDependencyLayer(
        project, planBuilder, libDirectory, "project dependencies", isProjectDependency);
  }

  private void addDependencyLayer(
      Project project,
      ContainerBuildPlan.Builder planBuilder,
      Path libDirectory,
      String layerName,
      Predicate predicate)
      throws IOException {
    FileEntriesLayer.Builder layerBuilder = FileEntriesLayer.builder().setName(layerName);

    String relativePathInLib =
        project.getBuildDir().toURI().relativize(libDirectory.toUri()).toString();

    try (Stream files = Files.list(libDirectory)) {
      files
          .filter(predicate)
          .forEach(
              path -> {
                layerBuilder.addEntry(
                    path,
                    appRoot.resolve(relativePathInLib).resolve(path.getFileName().toString()));
              });
    }

    FileEntriesLayer layer = layerBuilder.build();
    if (!layer.getEntries().isEmpty()) {
      planBuilder.addLayer(layer);
    }
  }

  private void readJibConfigurations(Project project) {
    JibExtension jibPlugin = project.getExtensions().findByType(JibExtension.class);
    String appRootValue = jibPlugin.getContainer().getAppRoot();
    if (!Strings.isNullOrEmpty(appRootValue)) {
      appRoot = AbsoluteUnixPath.get(appRootValue);
    }
    jvmFlags = jibPlugin.getContainer().getJvmFlags();
    jarResolver = new JarResolverFactory().getJarResolver(packageType);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy