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

org.wildfly.swarm.plugin.FractionRegistry Maven / Gradle / Ivy

package org.wildfly.swarm.plugin;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Dependency;
import org.apache.maven.project.MavenProject;
import org.yaml.snakeyaml.Yaml;

/**
 * @author Bob McWhirter
 * @author Ken Finnigan
 */
public class FractionRegistry {

    public static final String THORNTAIL_GROUP_ID = "io.thorntail";

    public static final String SPI_ARTIFACT_ID = "spi";

    private static final String FRACTION_TAGS_PROPERTY_NAME = "swarm.fraction.tags";

    private static final String FRACTION_INTERNAL_PROPERTY_NAME = "swarm.fraction.internal";

    private static final String FRACTION_STABILITY_PROPERTY_NAME = "swarm.fraction.stability";

    private static final String FRACTION_BOOTSTRAP_PROPERTY = "swarm.fraction.bootstrap";

    private static final String FRACTION_SCOPE_PROPERTY_NAME = "swarm.fraction.scope";

    private static final String BOM_PROPERTY = "swarm.bom";

    private Map fractionRegistry = new HashMap<>();

    private Map dependencyRegistry = new HashMap<>();

    public static final FractionRegistry INSTANCE = new FractionRegistry();

    private final List bomInclusions = new ArrayList<>();

    private FractionRegistry() {

    }

    public FractionMetadata of(DependencyMetadata dependency) {
        Key key = Key.of(dependency);
        return fractionRegistry.get(key);
    }

    public FractionMetadata of(MavenProject project) {
        if (project == null) {
            return null;
        }
        if (project.getGroupId().equals(THORNTAIL_GROUP_ID) && project.getArtifactId().equals("bootstrap")) {
            return null;
        }
        Key key = Key.of(project);
        if (this.fractionRegistry.containsKey(key)) {
            return this.fractionRegistry.get(key);
        }

        FractionMetadata meta = build(project);
        this.fractionRegistry.put(key, meta);
        return meta;
    }

    private FractionMetadata build(MavenProject project) {

        FractionMetadata meta = new FractionMetadata(project.getGroupId(), project.getArtifactId(), project.getVersion(),
                                                     project.getProperties().getProperty(FRACTION_SCOPE_PROPERTY_NAME));

        meta.setName(project.getName());
        meta.setDescription(project.getDescription());

        String stabilityName = project.getProperties().getProperty(FRACTION_STABILITY_PROPERTY_NAME);

        if (stabilityName != null) {
            StabilityLevel stabilityLevel;
            try {
                stabilityLevel = StabilityLevel.valueOf(stabilityName.toUpperCase());
            } catch (NullPointerException | IllegalArgumentException e) {
                stabilityLevel = StabilityLevel.UNSTABLE;
            }
            meta.setStabilityIndex(stabilityLevel);
        }

        String tags = project.getProperties().getProperty(FRACTION_TAGS_PROPERTY_NAME);
        if (tags != null) {
            meta.setTags(Arrays.asList(tags.split(",")));
        }

        String internal = project.getProperties().getProperty(FRACTION_INTERNAL_PROPERTY_NAME);
        if (internal != null && internal.equals("true")) {
            meta.setInternal(true);
        }

        String bootstrap = project.getProperties().getProperty(FRACTION_BOOTSTRAP_PROPERTY);
        if (bootstrap != null) {
            meta.setBootstrap(bootstrap);
        }

        File baseDir = project.getBasedir();
        if (baseDir != null && baseDir.exists()) {
            Path moduleConf = Paths.get(project.getBasedir().getAbsolutePath(), "module.conf");
            if (Files.exists(moduleConf)) {
                meta.setModuleConf(moduleConf);
            }
            Path manifest = Paths.get(project.getBasedir().getAbsolutePath(), "target", "classes", "META-INF", "fraction-manifest.yaml");
            if (Files.exists(manifest)) {
                Yaml yaml = new Yaml();
                try (FileReader reader = new FileReader(manifest.toFile())) {
                    Map result = (Map) yaml.load(reader);
                    List transitiveDeps = (List) result.get("transitive-dependencies");
                    if (transitiveDeps != null) {
                        for (String each : transitiveDeps) {
                            meta.addTransitiveDependency(DependencyMetadata.fromString(each));
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        meta.setJavaFraction(findJavaFraction(project));

        if (!meta.isFraction()) {
            String includeInBOM = project.getProperties().getProperty(BOM_PROPERTY);
            if (includeInBOM != null) {
                DependencyMetadata dep = new DependencyMetadata(meta);
                this.bomInclusions.add(dep);

            }

            // not a fraction, quit.
            return null;
        }

        meta.setHasJavaCode(hasJavaCode(project));
        meta.setBaseModulePath(baseModulePath(meta));
        findDetectorClasses(project, meta);

        project.getModel().getDependencies()
                .stream()
                .filter(d -> d.getScope().equals("compile"))
                .forEach(d -> {
                    Key key = Key.of(d);

                    DependencyMetadata depMeta = this.dependencyRegistry.get(key);
                    if (depMeta == null) {
                        depMeta = new DependencyMetadata(d.getGroupId(), d.getArtifactId(), d.getVersion(), d.getClassifier(), d.getType());
                        this.dependencyRegistry.put(key, depMeta);
                    }

                    meta.addDependency(depMeta);
                });

        //System.err.println("-->" + project.getArtifact().getFile());


        return meta;
    }

    private void findDetectorClasses(MavenProject project, FractionMetadata meta) {
        Path src = Paths.get(project.getBuild().getSourceDirectory());

        if (Files.exists(src)) {
            try {
                Files.walkFileTree(src, new SimpleFileVisitor() {
                    boolean insideDetectPackage = false;

                    @Override
                    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                        if (dir.endsWith("detect")) {
                            insideDetectPackage = true;
                        }
                        return FileVisitResult.CONTINUE;
                    }

                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                        if (insideDetectPackage) {
                            meta.addDetectorClass(src.relativize(file), file);
                        }
                        return super.visitFile(file, attrs);
                    }

                    @Override
                    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                        if (insideDetectPackage) {
                            return FileVisitResult.TERMINATE;
                        }
                        return super.postVisitDirectory(dir, exc);
                    }
                });
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static Path baseModulePath(FractionMetadata meta) {
        Path path = meta.getJavaFraction();
        if (path != null) {
            return path.getParent();
        }

        path = Paths.get(meta.getGroupId().replace('.', File.separatorChar) + File.separatorChar + meta.getArtifactId().replace('-', File.separatorChar));
        return path;
    }

    private static boolean hasJavaCode(MavenProject project) {
        Path src = Paths.get(project.getBuild().getSourceDirectory());

        AtomicReference hasJava = new AtomicReference<>(false);

        if (Files.exists(src)) {
            try {
                Files.walkFileTree(src, new SimpleFileVisitor() {
                    boolean insideDetectPackage = false;

                    @Override
                    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                        if (dir.endsWith("detect")) {
                            insideDetectPackage = true;
                        }
                        return FileVisitResult.CONTINUE;
                    }

                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                        if (!insideDetectPackage && file.toString().endsWith(".java")) {
                            hasJava.set(true);
                            return FileVisitResult.TERMINATE;
                        }
                        return super.visitFile(file, attrs);
                    }

                    @Override
                    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                        if (insideDetectPackage) {
                            insideDetectPackage = false;
                        }
                        return super.postVisitDirectory(dir, exc);
                    }
                });
            } catch (IOException e) {
                // ignore
            }
        }

        return hasJava.get();
    }

    private static Path findJavaFraction(MavenProject project) {
        if (project.getGroupId().equals(THORNTAIL_GROUP_ID) && project.getArtifactId().equals(SPI_ARTIFACT_ID)) {
            return null;
        }
        Path src = Paths.get(project.getBuild().getSourceDirectory());

        AtomicReference javaFraction = new AtomicReference<>();

        if (Files.exists(src)) {
            try {
                Files.walkFileTree(src, new SimpleFileVisitor() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                        if (file.toString().endsWith("Fraction.java")) {
                            Path path = src.relativize(file);
                            javaFraction.set(path);
                            return FileVisitResult.TERMINATE;
                        }
                        return super.visitFile(file, attrs);
                    }
                });
            } catch (IOException e) {
                // ignore
            }
        }

        return javaFraction.get();
    }

    public List bomInclusions() {
        return this.bomInclusions;
    }

    private static class Key {
        private final String groupId;

        private final String artifactId;

        private final String version;

        private final String classifier;

        private final String packaging;


        Key(String groupId, String artifactId, String version, String classifier, String packaging) {
            this.groupId = groupId;
            this.artifactId = artifactId;
            this.version = version;
            this.classifier = classifier;
            this.packaging = packaging;
        }

        String compositeKey() {
            return this.groupId + ":" + this.artifactId + ":" + this.version + ":" + this.classifier + ":" + this.packaging;
        }

        @Override
        public int hashCode() {
            return compositeKey().hashCode();
        }

        @Override
        public boolean equals(Object obj) {
            return obj instanceof Key && compositeKey().equals(((Key) obj).compositeKey());
        }

        @Override
        public String toString() {
            return compositeKey();
        }

        public static Key of(MavenProject project) {
            return new Key(project.getGroupId(), project.getArtifactId(), project.getVersion(), null, project.getPackaging());
        }

        public static Key of(Artifact artifact) {
            return new Key(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), artifact.getClassifier(), artifact.getType());
        }

        public static Key of(DependencyMetadata dependency) {
            return new Key(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), dependency.getClassifier(), dependency.getPackaging());
        }

        public static Key of(Dependency dependency) {
            return new Key(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), dependency.getClassifier(), dependency.getType());
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy