@Override
  public List<FileEntriesLayer> createLayers() throws IOException {
    // Clear the exploded-artifact root first
    if (Files.exists(targetExplodedJarRoot)) {
      MoreFiles.deleteRecursively(targetExplodedJarRoot, RecursiveDeleteOption.ALLOW_INSECURE);
    }

    try (JarFile jarFile = new JarFile(jarPath.toFile())) {
      ZipUtil.unzip(jarPath, targetExplodedJarRoot, true);
      ZipEntry layerIndex = jarFile.getEntry(BOOT_INF + "/layers.idx");
      if (layerIndex != null) {
        return createLayersForLayeredSpringBootJar(targetExplodedJarRoot);
      }

      Predicate<Path> isFile = Files::isRegularFile;

      // Non-snapshot layer
      Predicate<Path> isInBootInfLib =
          path -> path.startsWith(targetExplodedJarRoot.resolve(BOOT_INF).resolve("lib"));
      Predicate<Path> isSnapshot = path -> path.getFileName().toString().contains("SNAPSHOT");
      Predicate<Path> isInBootInfLibAndIsNotSnapshot = isInBootInfLib.and(isSnapshot.negate());
      Predicate<Path> nonSnapshotPredicate = isFile.and(isInBootInfLibAndIsNotSnapshot);
      FileEntriesLayer nonSnapshotLayer =
          ArtifactLayers.getDirectoryContentsAsLayer(
              ArtifactLayers.DEPENDENCIES,
              targetExplodedJarRoot,
              nonSnapshotPredicate,
              JarLayers.APP_ROOT);

      // Snapshot layer
      Predicate<Path> isInBootInfLibAndIsSnapshot = isInBootInfLib.and(isSnapshot);
      Predicate<Path> snapshotPredicate = isFile.and(isInBootInfLibAndIsSnapshot);
      FileEntriesLayer snapshotLayer =
          ArtifactLayers.getDirectoryContentsAsLayer(
              ArtifactLayers.SNAPSHOT_DEPENDENCIES,
              targetExplodedJarRoot,
              snapshotPredicate,
              JarLayers.APP_ROOT);

      // Spring-boot-loader layer.
      Predicate<Path> isLoader = path -> path.startsWith(targetExplodedJarRoot.resolve("org"));
      Predicate<Path> loaderPredicate = isFile.and(isLoader);
      FileEntriesLayer loaderLayer =
          ArtifactLayers.getDirectoryContentsAsLayer(
              "spring-boot-loader", targetExplodedJarRoot, loaderPredicate, JarLayers.APP_ROOT);

      // Classes layer.
      Predicate<Path> isClass = path -> path.getFileName().toString().endsWith(".class");
      Predicate<Path> isInBootInfClasses =
          path -> path.startsWith(targetExplodedJarRoot.resolve(BOOT_INF).resolve("classes"));
      Predicate<Path> classesPredicate = isInBootInfClasses.and(isClass);
      FileEntriesLayer classesLayer =
          ArtifactLayers.getDirectoryContentsAsLayer(
              ArtifactLayers.CLASSES, targetExplodedJarRoot, classesPredicate, JarLayers.APP_ROOT);

      // Resources layer.
      Predicate<Path> isInMetaInf =
          path -> path.startsWith(targetExplodedJarRoot.resolve("META-INF"));
      Predicate<Path> isResource = isInMetaInf.or(isInBootInfClasses.and(isClass.negate()));
      Predicate<Path> resourcesPredicate = isFile.and(isResource);
      FileEntriesLayer resourcesLayer =
          ArtifactLayers.getDirectoryContentsAsLayer(
              ArtifactLayers.RESOURCES,
              targetExplodedJarRoot,
              resourcesPredicate,
              JarLayers.APP_ROOT);

      return Arrays.asList(
          nonSnapshotLayer, loaderLayer, snapshotLayer, resourcesLayer, classesLayer);
    }
  }
Constructor for {@link SpringBootExplodedProcessor}.

@param jarPath path to jar file
@param targetExplodedJarRoot path to exploded-jar root
@param jarJavaVersion jar java version
jib-cli/src/main/java/com/google/cloud/tools/jib/cli/jar/SpringBootExplodedProcessor.java