import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * This is {@link CheckSpringConfigurationFactories}.
 *
 * @author Misagh Moayyed
 * @since 6.3.0
 */
public class CheckSpringConfigurationFactories {
    public static void main(final String[] args) throws Exception {
        checkPattern(args[0]);
    }

    private static void print(final String message, final Object... args) {
        //CHECKSTYLE:OFF
        System.out.printf(message, args);
        System.out.println();
        //CHECKSTYLE:ON
    }

    private static String readFile(final Path file) {
        try {
            return Files.readString(file);
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static boolean checkProjectContainsSpringConfigurations(final String projectPath,
                                                                    final File springFactoriesFile) throws Exception {
        if (springFactoriesFile.exists()) {
            return true;
        }
        final var pass = new AtomicBoolean(true);
        Files.walk(Paths.get(projectPath))
            .filter(Files::isRegularFile)
            .forEach(file -> {
                if (file.toFile().getName().endsWith("Configuration.java")
                    && readFile(file).contains("@Configuration")) {
                    print("Configuration class %s is missing from %s", file, springFactoriesFile);
                    pass.set(false);
                }
            });
        if (!pass.get()) {
            print("Project %s is missing a spring.factories file at %s", projectPath, springFactoriesFile);
        }
        return pass.get();
    }

    private static boolean checkForSpringConfigurationFactories(final String projectPath,
                                                                final String configurations,
                                                                final File springFactoriesFile) {
        var classes = configurations.split(",");
        for (var it : Arrays.asList(classes)) {
            var sourcePath = "/src/main/java/".replace("/", String.valueOf(File.separator));
            var clazz = projectPath + sourcePath + it.replace(".", String.valueOf(File.separator)) + ".java";
            var configurationFile = new File(clazz);
            if (!configurationFile.exists()) {
                print("Spring configuration class %s does not exist in %s", clazz, springFactoriesFile);
                return false;
            }
        }
        return true;
    }

    protected static void checkPattern(final String arg) throws IOException {
        final var count = new AtomicInteger(0);

        Files.walk(Paths.get(arg))
            .filter(file -> Files.isDirectory(file) && file.toFile().getAbsolutePath().endsWith("src/main/resources/META-INF"))
            .forEach(dir -> {
                try {
                    var projectPath = dir.getParent().getParent().getParent().getParent().toFile().getPath();
                    var springFactoriesFile = new File(dir.toFile(), "spring.factories");
                    if (springFactoriesFile.exists()) {
                        var properties = new Properties();

                        properties.load(new FileReader(springFactoriesFile));

                        if (properties.isEmpty()) {
                            print("spring.factories file %s is empty", springFactoriesFile);
                            count.incrementAndGet();
                        }

                        if (properties.containsKey("org.springframework.cloud.bootstrap.BootstrapConfiguration")) {
                            var classes = (String) properties.get("org.springframework.cloud.bootstrap.BootstrapConfiguration");
                            if (!checkForSpringConfigurationFactories(projectPath, classes, springFactoriesFile)) {
                                count.incrementAndGet();
                            }
                        }
                        if (properties.containsKey("org.springframework.boot.autoconfigure.EnableAutoConfiguration")) {
                            var classes = (String) properties.get("org.springframework.boot.autoconfigure.EnableAutoConfiguration");
                            if (!checkForSpringConfigurationFactories(projectPath, classes, springFactoriesFile)) {
                                count.incrementAndGet();
                            }
                        }
                    } else if (!checkProjectContainsSpringConfigurations(projectPath, springFactoriesFile)) {
                        count.incrementAndGet();
                    }
                } catch (final Exception e) {
                    throw new RuntimeException(e);
                }
            });

        if (count.intValue() > 0) {
            System.exit(1);
        }
    }
}

@@ -544,23 +544,101 @@
    check
-Pattern
+SpringFactoryConfigurations(args%5B0%5D);%0A        checkMissingSpringFactoryConfigurations
 (args%5B0%5D
@@ -1358,30 +1358,24 @@
   %7D%0A        
-final 
 var pass = n
@@ -1465,15 +1465,19 @@
 ter(
+f -%3E 
 Files
-::
+.
 isRe
@@ -1489,65 +1489,16 @@
 File
-)%0A            .forEach(file -%3E %7B%0A                if (file
+(f) && f
 .toF
@@ -1543,16 +1543,17 @@
 n.java%22)
+)
 %0A       
@@ -1561,19 +1561,47 @@
     
-        && 
+.forEach(file -%3E %7B%0A                if (
 read
@@ -2893,15 +2893,42 @@
 heck
-Pattern
+MissingSpringFactoryConfigurations
 (fin
@@ -2971,21 +2971,1016 @@
         
-final
+Files.walk(Paths.get(arg))%0A            .filter(f -%3E Files.isRegularFile(f) && f.toFile().getName().endsWith(%22Configuration.java%22))%0A            .forEach(file -%3E %7B%0A                if (readFile(file).contains(%22@Configuration%22)) %7B%0A                    var parent = file.getParent();%0A                    while (parent != null && !parent.toFile().getName().equals(%22src%22)) %7B%0A                        parent = parent.getParent();%0A                    %7D%0A                    var springFactoriesFile = new File(parent.toFile(), %22main/resources/META-INF/spring.factories%22);%0A                    if (!springFactoriesFile.exists()) %7B%0A                        print(%22Configuration class %25s is missing from %25s%22,%0A                            file.toFile().getAbsolutePath(), springFactoriesFile.getAbsolutePath());%0A                        System.exit(1);%0A                    %7D%0A                %7D%0A            %7D);%0A    %7D%0A%0A    protected static void checkSpringFactoryConfigurations(final String arg) throws IOException %7B%0A       
  var cou

make config classes are marked in factories