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

info.novatec.testit.webtester.internal.implementation.pages.PageImplementation Maven / Gradle / Ivy

package info.novatec.testit.webtester.internal.implementation.pages;

import static net.bytebuddy.matcher.ElementMatchers.isAbstract;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
import static net.bytebuddy.matcher.ElementMatchers.isDefaultMethod;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;

import java.lang.reflect.InvocationHandler;
import java.util.HashMap;
import java.util.Map;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.dynamic.DynamicType.Builder;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.implementation.DefaultMethodCall;
import net.bytebuddy.implementation.InvocationHandlerAdapter;

import info.novatec.testit.webtester.internal.ClasspathUtils;
import info.novatec.testit.webtester.internal.implementation.advices.ActionAdvice;
import info.novatec.testit.webtester.internal.implementation.invocationhandler.IdentifyUsingInvocationHandler;
import info.novatec.testit.webtester.internal.implementation.invocationhandler.KotlinDefaultMethodHandler;
import info.novatec.testit.webtester.pagefragments.annotations.IdentifyUsing;
import info.novatec.testit.webtester.pages.Page;


final class PageImplementation {

    private static final Map, Class>> CACHE = new HashMap<>();

    static Class getOrCreate(Class pageType) {
        ClassLoader classLoader = pageType.getClassLoader();
        Map, Class> implementationMap =
            CACHE.computeIfAbsent(classLoader, cl -> new HashMap<>());
        return implementationMap.computeIfAbsent(pageType, PageImplementation::create);
    }

    private static Class create(Class pageType) {

        String className = pageType.getCanonicalName() + "$$Impl";
        ClassLoader classLoader = pageType.getClassLoader();

        InvocationHandler identifyUsingHandler = new IdentifyUsingInvocationHandler();

        Builder pageTypeBuilder = new ByteBuddy()//
            .with(ClassFileVersion.JAVA_V8)
            .subclass(BasePage.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS)
            .implement(pageType)
            .name(className);

        if (ClasspathUtils.KOTLIN_MODULE_LOADED) {
            pageTypeBuilder = addKotlinImplementations(pageTypeBuilder, pageType);
        }

        pageTypeBuilder = pageTypeBuilder//
            .method(isDefaultMethod())//
            .intercept(Advice.to(ActionAdvice.class)//
                .wrap(DefaultMethodCall.prioritize(pageType)));

        pageTypeBuilder = pageTypeBuilder//
            .method(isAbstract().and(isAnnotatedWith(IdentifyUsing.class)).and(takesArguments(0)))
            .intercept(InvocationHandlerAdapter.of(identifyUsingHandler));

        return pageTypeBuilder.make().load(classLoader).getLoaded();

    }

    private static Builder addKotlinImplementations(Builder pageTypeBuilder,
        Class pageType) {
        try {
            Class kotlinPage = Class.forName(ClasspathUtils.KOTLIN_PAGE_CLASS);
            if (kotlinPage.isAssignableFrom(pageType)) {
                InvocationHandler kotlinDefaultMethodHandler = new KotlinDefaultMethodHandler();
                return pageTypeBuilder//
                    .method(isAbstract())//
                    .intercept(InvocationHandlerAdapter.of(kotlinDefaultMethodHandler));
            }
            return pageTypeBuilder;
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException("could not load Kotlin Page implementation", e);
        }
    }

    private PageImplementation() {
        // utility class
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy