![JAR search and dependency download from the Maven repository](/logo.png)
org.mule.tck.junit4.ExtensionsFunctionalTestCase Maven / Gradle / Ivy
/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.tck.junit4;
import static org.mule.api.lifecycle.LifecycleUtils.initialiseIfNeeded;
import static org.mule.util.IOUtils.getResourceAsUrl;
import static org.springframework.util.ReflectionUtils.findMethod;
import org.mule.DefaultMuleContext;
import org.mule.api.MuleContext;
import org.mule.api.config.ConfigurationBuilder;
import org.mule.api.registry.ServiceRegistry;
import org.mule.config.builders.AbstractConfigurationBuilder;
import org.mule.extension.ExtensionManager;
import org.mule.extension.introspection.Extension;
import org.mule.extension.introspection.ExtensionFactory;
import org.mule.extension.introspection.declaration.Describer;
import org.mule.extension.resources.GeneratedResource;
import org.mule.extension.resources.ResourcesGenerator;
import org.mule.extension.resources.spi.GenerableResourceContributor;
import org.mule.module.extension.internal.introspection.AnnotationsBasedDescriber;
import org.mule.module.extension.internal.introspection.DefaultExtensionFactory;
import org.mule.module.extension.internal.manager.DefaultExtensionManager;
import org.mule.module.extension.internal.resources.AbstractResourcesGenerator;
import org.mule.registry.SpiServiceRegistry;
import org.mule.util.ArrayUtils;
import com.google.common.collect.ImmutableList;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.List;
import org.apache.commons.io.FileUtils;
/**
* Base test class for {@link FunctionalTestCase}s
* that make use of components generated through the extensions API.
*
* The value added by this class in comparison to a traditional
* {@link FunctionalTestCase} is that before creating
* the {@link MuleContext}, it creates a {@link ExtensionManager}
* and automatically discovers extensions by delegating on
* {@link ExtensionManager#discoverExtensions(ClassLoader)}.
*
* By default, standard extension discovery will be
* performed by invoking {@link ExtensionManager#discoverExtensions(ClassLoader)}.
* Although this behavior suits most use cases, it can be time consuming because of
* all the classpath scanning and the overhead of initialising extensions that
* are most likely not used in this tests. As the number of extensions available grows,
* the problem gets worst. For those cases, you can override the {@link #getDescribers()}
* and specify which describers are to be used to initialise the extensions manager. In that way,
* extensions discovery is skipped and you only initialise what you need.
*
* Once extensions are discovered and described,
* a {@link ResourcesGenerator} is used to automatically
* generate any backing resources needed (for example, XSD schemas, spring bundles,
* service registration files, etc).
*
* In this way, the user experience is greatly simplified when running the test
* either through an IDE or build tool such as maven or gradle.
*
* Since this class extends {@link FunctionalTestCase}, a new {@link MuleContext}
* is created per each test. That also means that a new {@link ExtensionManager}
* is created per test.
*
* @since 3.7.0
*/
public abstract class ExtensionsFunctionalTestCase extends FunctionalTestCase
{
private final ServiceRegistry serviceRegistry = new SpiServiceRegistry();
private final ExtensionFactory extensionFactory = new DefaultExtensionFactory(serviceRegistry);
private ExtensionManager extensionManager;
private File generatedResourcesDirectory;
/**
* Performs all the logic inherited from the super class, plus invokes
* {@link #createExtensionsManager()}
*
* @throws Exception in case of any failure
*/
@Override
protected void doSetUpBeforeMuleContextCreation() throws Exception
{
super.doSetUpBeforeMuleContextCreation();
createExtensionsManager();
}
/**
* Implement this method to limit the amount of extensions
* initialised by providing the {@link Describer}s for
* the extensions that you actually want to use for this test.
* Returning a {@code null} or empty array will cause the
* {@link #getAnnotatedExtensionClasses()} method to be considered.
* Default implementation of this method returns {@code null}
*/
protected Describer[] getDescribers()
{
return null;
}
/**
* Implement this method to limit the amount of extensions
* initialised by providing the annotated classes which define
* the extensions that you actually want to use for this test.
* Returning a {@code null} or empty array forces the
* {@link ExtensionManager} to perform a full classpath discovery.
* Default implementation of this method returns {@code null}.
* This method will only be considered if {@link #getDescribers()}
* returns {@code null}
*/
protected Class>[] getAnnotatedExtensionClasses()
{
return null;
}
/**
* Adds a {@link ConfigurationBuilder} that sets the {@link #extensionManager}
* into the {@link #muleContext}. This {@link ConfigurationBuilder} is set
* as the first element of the {@code builders} {@link List}
*
* @param builders the list of {@link ConfigurationBuilder}s that will be used to initialise the {@link #muleContext}
*/
@Override
protected final void addBuilders(List builders)
{
super.addBuilders(builders);
builders.add(0, new AbstractConfigurationBuilder()
{
@Override
protected void doConfigure(MuleContext muleContext) throws Exception
{
((DefaultMuleContext) muleContext).setExtensionManager(extensionManager);
initialiseIfNeeded(extensionManager, muleContext);
}
});
}
private List getGenerableResourceContributors()
{
return ImmutableList.copyOf(serviceRegistry.lookupProviders(GenerableResourceContributor.class));
}
private void createExtensionsManager() throws Exception
{
extensionManager = new DefaultExtensionManager();
Describer[] describers = getDescribers();
if (ArrayUtils.isEmpty(describers))
{
Class>[] annotatedClasses = getAnnotatedExtensionClasses();
if (!ArrayUtils.isEmpty(annotatedClasses))
{
describers = new Describer[annotatedClasses.length];
int i = 0;
for (Class> annotatedClass : annotatedClasses)
{
describers[i++] = new AnnotationsBasedDescriber(annotatedClass);
}
}
}
if (ArrayUtils.isEmpty(describers))
{
extensionManager.discoverExtensions(getClass().getClassLoader());
}
else
{
loadExtensionsFromDescribers(extensionManager, describers);
}
generatedResourcesDirectory = getGenerationTargetDirectory();
ResourcesGenerator generator = new ExtensionsTestInfrastructureResourcesGenerator(serviceRegistry, generatedResourcesDirectory);
List resourceContributors = getGenerableResourceContributors();
for (Extension extension : extensionManager.getExtensions())
{
for (GenerableResourceContributor contributor : resourceContributors)
{
contributor.contribute(extension, generator);
}
}
generateResourcesAndAddToClasspath(generator);
}
private void loadExtensionsFromDescribers(ExtensionManager extensionManager, Describer[] describers)
{
for (Describer describer : describers)
{
extensionManager.registerExtension(extensionFactory.createFrom(describer.describe()));
}
}
private void generateResourcesAndAddToClasspath(ResourcesGenerator generator) throws Exception
{
ClassLoader cl = getClass().getClassLoader();
Method method = findMethod(cl.getClass(), "addURL", URL.class);
method.setAccessible(true);
for (GeneratedResource resource : generator.dumpAll())
{
URL generatedResourceURL = new File(generatedResourcesDirectory, resource.getFilePath()).toURI().toURL();
method.invoke(cl, generatedResourceURL);
}
}
private File getGenerationTargetDirectory()
{
URL url = getResourceAsUrl(getEffectiveConfigFile(), getClass(), true, true);
File targetDirectory = new File(FileUtils.toFile(url).getParentFile(), "META-INF");
if (!targetDirectory.exists() && !targetDirectory.mkdir())
{
throw new RuntimeException("Could not create target directory " + targetDirectory.getAbsolutePath());
}
return targetDirectory;
}
private String getEffectiveConfigFile()
{
String configFile = getConfigFile();
if (configFile != null)
{
return configFile;
}
configFile = getConfigFileFromSplittable(getConfigurationResources());
if (configFile != null)
{
return configFile;
}
configFile = getConfigFileFromSplittable(getConfigResources());
if (configFile != null)
{
return configFile;
}
String[] configFiles = getConfigFiles();
if (!ArrayUtils.isEmpty(configFiles))
{
return configFiles[0].trim();
}
throw new IllegalArgumentException("No valid config file was specified");
}
private String getConfigFileFromSplittable(String configFile)
{
if (configFile != null)
{
return configFile.split(",")[0].trim();
}
return null;
}
private class ExtensionsTestInfrastructureResourcesGenerator extends AbstractResourcesGenerator
{
private File targetDirectory;
private ExtensionsTestInfrastructureResourcesGenerator(ServiceRegistry serviceRegistry, File targetDirectory)
{
super(serviceRegistry);
this.targetDirectory = targetDirectory;
}
@Override
protected void write(GeneratedResource resource)
{
File targetFile = new File(targetDirectory, resource.getFilePath());
try
{
FileUtils.write(targetFile, resource.getContentBuilder().toString());
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy