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

io.smallrye.graphql.entry.http.IndexInitializer Maven / Gradle / Ivy

package io.smallrye.graphql.entry.http;

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Repeatable;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.jboss.jandex.CompositeIndex;
import org.jboss.jandex.IndexReader;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.Indexer;

import io.smallrye.graphql.api.Entry;
import io.smallrye.graphql.api.OneOf;
import io.smallrye.graphql.api.federation.Authenticated;
import io.smallrye.graphql.api.federation.ComposeDirective;
import io.smallrye.graphql.api.federation.Extends;
import io.smallrye.graphql.api.federation.External;
import io.smallrye.graphql.api.federation.FieldSet;
import io.smallrye.graphql.api.federation.Inaccessible;
import io.smallrye.graphql.api.federation.InterfaceObject;
import io.smallrye.graphql.api.federation.Key;
import io.smallrye.graphql.api.federation.Override;
import io.smallrye.graphql.api.federation.Provides;
import io.smallrye.graphql.api.federation.Requires;
import io.smallrye.graphql.api.federation.Shareable;
import io.smallrye.graphql.api.federation.Tag;
import io.smallrye.graphql.api.federation.link.Import;
import io.smallrye.graphql.api.federation.link.Link;
import io.smallrye.graphql.api.federation.link.Purpose;
import io.smallrye.graphql.api.federation.policy.Policy;
import io.smallrye.graphql.api.federation.policy.PolicyGroup;
import io.smallrye.graphql.api.federation.policy.PolicyItem;
import io.smallrye.graphql.api.federation.requiresscopes.RequiresScopes;
import io.smallrye.graphql.api.federation.requiresscopes.ScopeGroup;
import io.smallrye.graphql.api.federation.requiresscopes.ScopeItem;

/**
 * This creates an index from the classpath.
 *
 * @author Phillip Kruger ([email protected])
 */
public class IndexInitializer {

    public IndexView createIndex(Set urls) {
        List indexes = new ArrayList<>();

        // TODO: Read all jandex.idx in the classpath:
        // something like Enumeration systemResources = ClassLoader.getSystemResources(JANDEX_IDX);

        // Check in this war
        try (InputStream stream = getClass().getClassLoader().getResourceAsStream(JANDEX_IDX)) {
            IndexReader reader = new IndexReader(stream);
            IndexView i = reader.read();
            SmallRyeGraphQLServletLogging.log.loadedIndexFrom(JANDEX_IDX);
            indexes.add(i);
        } catch (IOException ex) {
            SmallRyeGraphQLServletLogging.log.generatingIndex();
        }

        // Classes in this artifact
        IndexView artifact = createIndexView(urls);
        indexes.add(artifact);

        IndexView custom = createCustomIndex();
        indexes.add(custom);

        return merge(indexes);
    }

    public IndexView createIndex() {
        Set urls = getUrlFromClassPath();
        return createIndexView(urls);
    }

    private IndexView createCustomIndex() {
        Indexer indexer = new Indexer();

        try {
            indexer.index(convertClassToInputStream(Map.class));
            indexer.index(convertClassToInputStream(Entry.class));
            indexer.index(convertClassToInputStream(Repeatable.class));

            // directives from the API module
            indexer.index(convertClassToInputStream(Authenticated.class));
            indexer.index(convertClassToInputStream(ComposeDirective.class));
            indexer.index(convertClassToInputStream(io.smallrye.graphql.api.Deprecated.class));
            indexer.index(convertClassToInputStream(java.lang.Deprecated.class));
            indexer.index(convertClassToInputStream(Extends.class));
            indexer.index(convertClassToInputStream(External.class));
            indexer.index(convertClassToInputStream(FieldSet.class));
            indexer.index(convertClassToInputStream(Import.class));
            indexer.index(convertClassToInputStream(Inaccessible.class));
            indexer.index(convertClassToInputStream(InterfaceObject.class));
            indexer.index(convertClassToInputStream(Key.class));
            indexer.index(convertClassToInputStream(Link.class));
            indexer.index(convertClassToInputStream(OneOf.class));
            indexer.index(convertClassToInputStream(Override.class));
            indexer.index(convertClassToInputStream(Policy.class));
            indexer.index(convertClassToInputStream(PolicyGroup.class));
            indexer.index(convertClassToInputStream(PolicyItem.class));
            indexer.index(convertClassToInputStream(Provides.class));
            indexer.index(convertClassToInputStream(Purpose.class));
            indexer.index(convertClassToInputStream(Requires.class));
            indexer.index(convertClassToInputStream(RequiresScopes.class));
            indexer.index(convertClassToInputStream(ScopeGroup.class));
            indexer.index(convertClassToInputStream(ScopeItem.class));
            indexer.index(convertClassToInputStream(Shareable.class));
            indexer.index(convertClassToInputStream(Tag.class));
            indexer.index(convertClassToInputStream(OneOf.class));
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
        return indexer.complete();
    }

    private InputStream convertClassToInputStream(Class clazz) {
        String resourceName = '/' + clazz.getName().replace('.', '/') + ".class";
        return clazz.getResourceAsStream(resourceName);
    }

    private IndexView createIndexView(Set urls) {
        Indexer indexer = new Indexer();
        for (URL url : urls) {
            try {
                if (url.toString().endsWith(DOT_JAR) || url.toString().endsWith(DOT_WAR)) {
                    SmallRyeGraphQLServletLogging.log.processingFile(url.toString());
                    processJar(url.openStream(), indexer);
                } else {
                    processFolder(url, indexer);
                }
            } catch (IOException ex) {
                SmallRyeGraphQLServletLogging.log.cannotProcessFile(url.toString(), ex);
            }
        }

        return indexer.complete();
    }

    private Set collectURLsFromClassPath() {
        Set urls = new HashSet<>();
        for (String s : System.getProperty(JAVA_CLASS_PATH).split(System.getProperty(PATH_SEPARATOR))) {
            try {
                urls.add(Paths.get(s).toUri().toURL());
            } catch (MalformedURLException e) {
                SmallRyeGraphQLServletLogging.log.cannotCreateUrl(e);
            }
        }

        return urls;
    }

    private void processFolder(URL url, Indexer indexer) throws IOException {
        try {
            Path folderPath = Paths.get(url.toURI());
            if (Files.isDirectory(folderPath)) {
                try (Stream walk = Files.walk(folderPath)) {

                    List collected = walk
                            .filter(Files::isRegularFile)
                            .collect(Collectors.toList());

                    for (Path c : collected) {
                        String entryName = c.getFileName().toString();
                        processFile(entryName, Files.newInputStream(c), indexer);
                    }
                }
            } else {
                SmallRyeGraphQLServletLogging.log.ignoringUrl(url);
            }

        } catch (URISyntaxException ex) {
            SmallRyeGraphQLServletLogging.log.couldNotProcessUrl(url, ex);
        }
    }

    private void processJar(InputStream inputStream, Indexer indexer) throws IOException {

        ZipInputStream zis = new ZipInputStream(inputStream, StandardCharsets.UTF_8);
        ZipEntry ze;

        while ((ze = zis.getNextEntry()) != null) {
            String entryName = ze.getName();
            processFile(entryName, zis, indexer);
        }
    }

    private void processFile(String fileName, InputStream is, Indexer indexer) throws IOException {
        if (fileName.endsWith(DOT_CLASS)) {
            SmallRyeGraphQLServletLogging.log.processingFile(fileName);
            indexer.index(is);
        } else if (fileName.endsWith(DOT_WAR) || fileName.endsWith(DOT_JAR)) {
            // necessary because of the thorntail arquillian adapter
            processJar(is, indexer);
        }
    }

    private IndexView merge(Collection indexes) {
        return CompositeIndex.create(indexes);
    }

    private Set getUrlFromClassPath() {
        Set urls = new HashSet<>();

        ClassLoader cl = ClassLoader.getSystemClassLoader();
        if (cl instanceof URLClassLoader) {
            urls.addAll(Arrays.asList(((URLClassLoader) cl).getURLs()));
        } else {
            urls.addAll(collectURLsFromClassPath());
        }
        return urls;
    }

    private static final String DOT_JAR = ".jar";
    private static final String DOT_WAR = ".war";
    private static final String DOT_CLASS = ".class";
    private static final String JAVA_CLASS_PATH = "java.class.path";
    private static final String PATH_SEPARATOR = "path.separator";
    private static final String JANDEX_IDX = "META-INF/jandex.idx";
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy