001/**
002 * Copyright (C) 2006-2018 Talend Inc. - www.talend.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.talend.sdk.component.junit.http.internal.junit5;
017
018import java.lang.annotation.Annotation;
019import java.lang.reflect.InvocationTargetException;
020import java.util.Optional;
021import java.util.concurrent.Executor;
022import java.util.function.Predicate;
023import java.util.function.Supplier;
024
025import javax.net.ssl.SSLContext;
026
027import org.junit.jupiter.api.extension.AfterAllCallback;
028import org.junit.jupiter.api.extension.AfterEachCallback;
029import org.junit.jupiter.api.extension.BeforeAllCallback;
030import org.junit.jupiter.api.extension.BeforeEachCallback;
031import org.junit.jupiter.api.extension.ExtensionContext;
032import org.talend.sdk.component.junit.base.junit5.JUnit5InjectionSupport;
033import org.talend.sdk.component.junit.http.api.HttpApiHandler;
034import org.talend.sdk.component.junit.http.api.ResponseLocator;
035import org.talend.sdk.component.junit.http.internal.impl.DefaultResponseLocator;
036import org.talend.sdk.component.junit.http.internal.impl.HandlerImpl;
037import org.talend.sdk.component.junit.http.internal.impl.Handlers;
038import org.talend.sdk.component.junit.http.junit5.HttpApi;
039import org.talend.sdk.component.junit.http.junit5.HttpApiInject;
040
041public class JUnit5HttpApi extends HttpApiHandler<JUnit5HttpApi>
042        implements BeforeAllCallback, AfterAllCallback, JUnit5InjectionSupport, AfterEachCallback, BeforeEachCallback {
043
044    private static final ExtensionContext.Namespace NAMESPACE =
045            ExtensionContext.Namespace.create(JUnit5HttpApi.class.getName());
046
047    @Override
048    public void beforeAll(final ExtensionContext extensionContext) {
049        final HttpApi config = extensionContext.getElement().map(c -> c.getAnnotation(HttpApi.class)).orElse(null);
050        if (config != null) {
051            setGlobalProxyConfiguration(config.globalProxyConfiguration());
052            setLogLevel(config.logLevel());
053            setPort(config.port());
054            newInstance(config.responseLocator(), ResponseLocator.class).ifPresent(this::setResponseLocator);
055            newInstance(config.headerFilter(), Predicate.class).ifPresent(this::setHeaderFilter);
056            newInstance(config.executor(), Executor.class).ifPresent(this::setExecutor);
057            newInstance(config.sslContext(), Supplier.class).map(s -> SSLContext.class.cast(s.get())).ifPresent(
058                    this::setSslContext);
059            setSkipProxyHeaders(config.skipProxyHeaders());
060            if (config.useSsl()) {
061                activeSsl();
062            }
063        }
064        extensionContext.getStore(NAMESPACE).put(HttpApiHandler.class.getName(), this);
065        final HandlerImpl<JUnit5HttpApi> handler = new HandlerImpl<>(this, null, null);
066        extensionContext.getStore(NAMESPACE).put(HandlerImpl.class.getName(), handler);
067        handler.start();
068    }
069
070    @Override
071    public void afterAll(final ExtensionContext extensionContext) {
072        HandlerImpl.class.cast(extensionContext.getStore(NAMESPACE).get(HandlerImpl.class.getName())).close();
073    }
074
075    @Override
076    public Class<? extends Annotation> injectionMarker() {
077        return HttpApiInject.class;
078    }
079
080    @Override
081    public void beforeEach(final ExtensionContext extensionContext) {
082        // test name
083        final ResponseLocator responseLocator = getResponseLocator();
084        if (!DefaultResponseLocator.class.isInstance(responseLocator)) {
085            return;
086        }
087        DefaultResponseLocator.class.cast(responseLocator).setTest(
088                extensionContext.getTestMethod().map(m -> m.getDeclaringClass().getName() + "_" + m.getName()).orElse(
089                        null));
090    }
091
092    @Override
093    public void afterEach(final ExtensionContext extensionContext) {
094        if (Handlers.isActive("capture")) {
095            Optional
096                    .of(getResponseLocator())
097                    .filter(DefaultResponseLocator.class::isInstance)
098                    .map(DefaultResponseLocator.class::cast)
099                    .ifPresent(r -> r.flush(Handlers.getBaseCapture()));
100        }
101    }
102
103    private static <T> Optional<T> newInstance(final Class<?> type, final Class<T> api) {
104        if (api == type) {
105            return Optional.empty();
106        }
107        try {
108            return Optional.of(api.cast(type.getConstructor().newInstance()));
109        } catch (final NoSuchMethodException | InstantiationException | IllegalAccessException e) {
110            throw new IllegalArgumentException(e);
111        } catch (final InvocationTargetException e) {
112            throw new IllegalStateException(e.getTargetException());
113        }
114    }
115}