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

org.jboss.arquillian.testcontainers.TestcontainerRegistry Maven / Gradle / Ivy

/*
 * Copyright The Arquillian Authors
 * SPDX-License-Identifier: Apache-2.0
 */
package org.jboss.arquillian.testcontainers;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.jboss.arquillian.testcontainers.api.Testcontainer;
import org.testcontainers.containers.GenericContainer;

/**
 * A registry to store the testcontainer descriptions.
 */
class TestcontainerRegistry implements Iterable {
    private final List containers;

    TestcontainerRegistry() {
        containers = new CopyOnWriteArrayList<>();
    }

    /**
     * Lookup the container in the test container instances. If more than one container is found for the type or
     * qualifier, an {@link IllegalArgumentException} is thrown.
     *
     * @param type          the type to lookup
     * @param testcontainer the test container annotation
     * @param qualifiers    any qualifying annotations
     *
     * @return the generic type
     */
    GenericContainer lookupOrCreate(final Class> type, final Testcontainer testcontainer,
            final List qualifiers) {
        GenericContainer result = lookup(type, qualifiers);
        if (result == null) {
            try {
                final Constructor> constructor = getConstructor(type, testcontainer);
                result = constructor.newInstance();
                this.containers.add(new TestcontainerDescription(testcontainer, result));
            } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
                throw new IllegalArgumentException(String.format("Could create container %s", type.getName()), e);
            }
        }
        return result;
    }

    /**
     * Lookup the container in the test container instances. If more than one container is found for the type or
     * qualifier, an {@link IllegalArgumentException} is thrown.
     *
     * @param type       the type to lookup
     * @param qualifiers any qualifying annotations
     *
     * @return the generic type
     */
    GenericContainer lookup(final Class type, final List qualifiers) {
        final List foundContainers = new ArrayList<>();
        if (qualifiers.isEmpty()) {
            for (TestcontainerDescription containerDesc : this.containers) {
                if (type.isAssignableFrom(containerDesc.instance.getClass())) {
                    foundContainers.add(containerDesc);
                }
            }
        } else {
            for (TestcontainerDescription containerDesc : this.containers) {
                for (Annotation qualifier : qualifiers) {
                    if (type.isAssignableFrom(containerDesc.instance.getClass())
                            && type.isAnnotationPresent(qualifier.annotationType())) {
                        foundContainers.add(containerDesc);
                    }
                }
            }
        }
        if (foundContainers.isEmpty()) {
            return null;
        }
        if (foundContainers.size() > 1) {
            throw new IllegalArgumentException(
                    String.format("Multiple containers found for type %s: %s", type, foundContainers));
        }
        return foundContainers.get(0).instance;
    }

    /**
     * @return an iterator for the container instances
     */
    @Override
    public Iterator iterator() {
        return containers.iterator();
    }

    private static Constructor> getConstructor(final Class> type,
            final Testcontainer testcontainer) throws NoSuchMethodException {
        @SuppressWarnings("unchecked")
        Class> constructType = (testcontainer.type() == GenericContainer.class) ? type
                : (Class>) testcontainer.type();
        if (constructType.isInterface()) {
            throw new IllegalArgumentException(
                    String.format("Type %s is an interface and cannot be created.", constructType));
        }
        return constructType.getConstructor();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy