Package org.powermock.tests.utils.impl

Source Code of org.powermock.tests.utils.impl.MockPolicyInitializerImpl

/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.powermock.tests.utils.impl;

import org.powermock.core.MockRepository;
import org.powermock.core.classloader.MockClassLoader;
import org.powermock.core.classloader.annotations.MockPolicy;
import org.powermock.core.spi.PowerMockPolicy;
import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
import org.powermock.mockpolicies.impl.MockPolicyClassLoadingSettingsImpl;
import org.powermock.mockpolicies.impl.MockPolicyInterceptionSettingsImpl;
import org.powermock.reflect.Whitebox;
import org.powermock.tests.utils.MockPolicyInitializer;

import java.lang.reflect.*;
import java.util.Arrays;
import java.util.Map.Entry;

/**
* The default implementation of the {@link MockPolicyInitializer} interface for
* mock policies.
*/
public class MockPolicyInitializerImpl implements MockPolicyInitializer {

    private final PowerMockPolicy[] mockPolicies;
    private final Class<? extends PowerMockPolicy>[] mockPolicyTypes;
    private final Class<?> testClass;

    public MockPolicyInitializerImpl(Class<? extends PowerMockPolicy>[] mockPolicies) {
        this(mockPolicies, false);
    }

    public MockPolicyInitializerImpl(Class<?> testClass) {
        this(getMockPolicies(testClass), testClass, false);
    }

    private MockPolicyInitializerImpl(Class<? extends PowerMockPolicy>[] mockPolicies, boolean internal) {
        this(mockPolicies, null, false);
    }

    private MockPolicyInitializerImpl(Class<? extends PowerMockPolicy>[] mockPolicies, Class<?> testClass, boolean internal) {
        this.testClass = testClass;
        if (internal) {
            mockPolicyTypes = null;
        } else {
            mockPolicyTypes = mockPolicies;
        }
        if (mockPolicies == null) {
            this.mockPolicies = new PowerMockPolicy[0];
        } else {
            this.mockPolicies = new PowerMockPolicy[mockPolicies.length];
            for (int i = 0; i < mockPolicies.length; i++) {
                this.mockPolicies[i] = Whitebox.newInstance(mockPolicies[i]);
            }
        }
    }

    public boolean isPrepared(String fullyQualifiedClassName) {
        MockPolicyClassLoadingSettings settings = getClassLoadingSettings();
        final boolean foundInSuppressStaticInitializer = Arrays.binarySearch(settings.getStaticInitializersToSuppress(), fullyQualifiedClassName) < 0;
        final boolean foundClassesLoadedByMockClassloader = Arrays.binarySearch(settings.getFullyQualifiedNamesOfClassesToLoadByMockClassloader(),
                fullyQualifiedClassName) < 0;
        return foundInSuppressStaticInitializer || foundClassesLoadedByMockClassloader;
    }

    public boolean needsInitialization() {
        MockPolicyClassLoadingSettings settings = getClassLoadingSettings();
        return settings.getStaticInitializersToSuppress().length > 0 || settings.getFullyQualifiedNamesOfClassesToLoadByMockClassloader().length > 0;
    }

    /**
     * {@inheritDoc}
     */
    public void initialize(ClassLoader classLoader) {
        if (classLoader instanceof MockClassLoader) {
            initialize((MockClassLoader) classLoader);
        }
    }

    /**
     *
     * {@inheritDoc}
     */
    private void initialize(MockClassLoader classLoader) {
        if (mockPolicies.length > 0) {
            MockPolicyClassLoadingSettings classLoadingSettings = getClassLoadingSettings();
            String[] fullyQualifiedNamesOfClassesToLoadByMockClassloader = classLoadingSettings
                    .getFullyQualifiedNamesOfClassesToLoadByMockClassloader();
            classLoader.addClassesToModify(fullyQualifiedNamesOfClassesToLoadByMockClassloader);

            if (testClass == null) {
                throw new IllegalStateException("Internal error: testClass should never be null when calling initialize on a mock policy");
            }

            classLoader.addClassesToModify(testClass.getName());
            Class<?>[] classes = testClass.getDeclaredClasses();
            for (Class<?> clazz : classes) {
                classLoader.addClassesToModify(clazz.getName());
            }
            Class<?>[] declaredClasses = testClass.getClasses();
            for (Class<?> clazz : declaredClasses) {
                classLoader.addClassesToModify(clazz.getName());
            }

            for (String string : classLoadingSettings.getStaticInitializersToSuppress()) {
                classLoader.addClassesToModify(string);
                MockRepository.addSuppressStaticInitializer(string);
            }

            invokeInitializeInterceptionSettingsFromClassLoader(classLoader);
        }
    }

    private void invokeInitializeInterceptionSettingsFromClassLoader(MockClassLoader classLoader) {
        try {
            final int sizeOfPolicies = mockPolicyTypes.length;
            Object mockPolicies = Array.newInstance(Class.class, sizeOfPolicies);
            for (int i = 0; i < sizeOfPolicies; i++) {
                final Class<?> policyLoadedByClassLoader = Class.forName(mockPolicyTypes[i].getName(), false, classLoader);
                Array.set(mockPolicies, i, policyLoadedByClassLoader);
            }
            final Class<?> thisTypeLoadedByMockClassLoader = Class.forName(this.getClass().getName(), false, classLoader);
            Object mockPolicyHandler = Whitebox.invokeConstructor(thisTypeLoadedByMockClassLoader, mockPolicies, true);
            Whitebox.invokeMethod(mockPolicyHandler, "initializeInterceptionSettings");
        } catch (InvocationTargetException e) {
            final Throwable targetException = e.getTargetException();
            if (targetException instanceof RuntimeException) {
                throw (RuntimeException) targetException;
            } else if (targetException instanceof Error) {
                throw (Error) targetException;
            } else {
                throw new RuntimeException(e);
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new IllegalStateException("PowerMock internal error: Failed to load class.", e);
        }
    }

    /*
     * This method IS used, but it's invoked using reflection from the
     * invokeInitializeInterceptionSettingsFromClassLoader method.
     */
    @SuppressWarnings("unused")
    private void initializeInterceptionSettings() {
        MockPolicyInterceptionSettings interceptionSettings = getInterceptionSettings();

        for (Method method : interceptionSettings.getMethodsToSuppress()) {
            MockRepository.addMethodToSuppress(method);
        }

        for (Entry<Method, InvocationHandler> entry : interceptionSettings.getProxiedMethods().entrySet()) {
            MockRepository.putMethodProxy(entry.getKey(), entry.getValue());
        }

        for (Entry<Method, Object> entry : interceptionSettings.getStubbedMethods().entrySet()) {
            final Method method = entry.getKey();
            final Object className = entry.getValue();
            MockRepository.putMethodToStub(method, className);
        }

        for (Field field : interceptionSettings.getFieldsToSuppress()) {
            MockRepository.addFieldToSuppress(field);
        }

        for (String type : interceptionSettings.getFieldTypesToSuppress()) {
            MockRepository.addFieldTypeToSuppress(type);
        }
    }

    private MockPolicyInterceptionSettings getInterceptionSettings() {
        MockPolicyInterceptionSettings settings = new MockPolicyInterceptionSettingsImpl();
        for (PowerMockPolicy mockPolicy : mockPolicies) {
            mockPolicy.applyInterceptionPolicy(settings);
        }
        return settings;
    }

    private MockPolicyClassLoadingSettings getClassLoadingSettings() {
        MockPolicyClassLoadingSettings settings = new MockPolicyClassLoadingSettingsImpl();
        for (PowerMockPolicy mockPolicy : mockPolicies) {
            mockPolicy.applyClassLoadingPolicy(settings);
        }
        return settings;
    }

    /**
     * Get the mock policies from a test-class.
     */
    @SuppressWarnings("unchecked")
    private static Class<? extends PowerMockPolicy>[] getMockPolicies(Class<?> testClass) {
        Class<? extends PowerMockPolicy>[] powerMockPolicies = new Class[0];
        if (testClass.isAnnotationPresent(MockPolicy.class)) {
            MockPolicy annotation = testClass.getAnnotation(MockPolicy.class);
            powerMockPolicies = annotation.value();
        }
        return powerMockPolicies;
    }
}
TOP

Related Classes of org.powermock.tests.utils.impl.MockPolicyInitializerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.