blob: a230d0cc96bda4b660a5286ac485faa6491ab84e [file] [log] [blame]
/*
* Copyright (c) 2016 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito.internal.configuration.plugins;
import org.mockito.plugins.PluginSwitch;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class PluginLoader {
private final DefaultMockitoPlugins plugins;
private final PluginInitializer initializer;
PluginLoader(DefaultMockitoPlugins plugins, PluginInitializer initializer) {
this.plugins = plugins;
this.initializer = initializer;
}
PluginLoader(PluginSwitch pluginSwitch) {
this(new DefaultMockitoPlugins(), new PluginInitializer(pluginSwitch, null, new DefaultMockitoPlugins()));
}
/**
* @deprecated Let's avoid adding more aliases. It complicates the API.
* Instead of an alias, we can use fully qualified class name of the alternative implementation.
* <p>
* Adds an alias for a class name to this plugin loader. Instead of the fully qualified type name,
* the alias can be used as a convenience name for a known plugin.
*/
@Deprecated
PluginLoader(PluginSwitch pluginSwitch, String alias) {
this(new DefaultMockitoPlugins(), new PluginInitializer(pluginSwitch, alias, new DefaultMockitoPlugins()));
}
/**
* Scans the classpath for given pluginType. If not found, default class is used.
*/
@SuppressWarnings("unchecked")
<T> T loadPlugin(final Class<T> pluginType) {
return (T) loadPlugin(pluginType, null);
}
/**
* Scans the classpath for given {@code preferredPluginType}. If not found scan for {@code
* alternatePluginType}. If neither a preferred or alternate plugin is found, default to default
* class of {@code preferredPluginType}.
*
* @return An object of either {@code preferredPluginType} or {@code alternatePluginType}
*/
@SuppressWarnings("unchecked")
<PreferredType, AlternateType> Object loadPlugin(final Class<PreferredType> preferredPluginType, final Class<AlternateType> alternatePluginType) {
try {
PreferredType preferredPlugin = initializer.loadImpl(preferredPluginType);
if (preferredPlugin != null) {
return preferredPlugin;
} else if (alternatePluginType != null) {
AlternateType alternatePlugin = initializer.loadImpl(alternatePluginType);
if (alternatePlugin != null) {
return alternatePlugin;
}
}
return plugins.getDefaultPlugin(preferredPluginType);
} catch (final Throwable t) {
return Proxy.newProxyInstance(preferredPluginType.getClassLoader(),
new Class<?>[]{preferredPluginType},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
throw new IllegalStateException("Could not initialize plugin: " + preferredPluginType + " (alternate: " + alternatePluginType + ")", t);
}
});
}
}
}