/*
* 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.runtime.deployment.model.api.plugin;
import static org.mule.runtime.api.util.Preconditions.checkArgument;
import static org.mule.runtime.deployment.model.api.plugin.ArtifactPluginDescriptor.MULE_PLUGIN_CLASSIFIER;
import static org.mule.runtime.module.artifact.classloader.ChildOnlyLookupStrategy.CHILD_ONLY;
import static org.mule.runtime.module.artifact.classloader.ParentFirstLookupStrategy.PARENT_FIRST;
import org.mule.runtime.container.api.ModuleRepository;
import org.mule.runtime.container.api.MuleModule;
import org.mule.runtime.container.internal.ContainerOnlyLookupStrategy;
import org.mule.runtime.module.artifact.classloader.ArtifactClassLoader;
import org.mule.runtime.module.artifact.classloader.ArtifactClassLoaderFactory;
import org.mule.runtime.module.artifact.classloader.ClassLoaderLookupPolicy;
import org.mule.runtime.module.artifact.classloader.LookupStrategy;
import org.mule.runtime.module.artifact.classloader.MuleArtifactClassLoader;
import org.mule.runtime.module.artifact.descriptor.BundleDependency;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Creates {@link ArtifactClassLoader} for application or domain plugin descriptors.
*/
public class ArtifactPluginClassLoaderFactory implements ArtifactClassLoaderFactory<ArtifactPluginDescriptor> {
private final ModuleRepository moduleRepository;
/**
* Creates a new factory
*
* @param moduleRepository provides access to the modules available on the container. Non null.
*/
public ArtifactPluginClassLoaderFactory(ModuleRepository moduleRepository) {
checkArgument(moduleRepository != null, "moduleRepository cannot be null");
this.moduleRepository = moduleRepository;
}
@Override
public ArtifactClassLoader create(String artifactId, ArtifactPluginDescriptor descriptor,
ClassLoader parent,
ClassLoaderLookupPolicy baseLookupPolicy) {
Map<String, LookupStrategy> pluginsLookupPolicies = new HashMap<>();
for (ArtifactPluginDescriptor dependencyPluginDescriptor : descriptor.getArtifactPluginDescriptors()) {
if (dependencyPluginDescriptor.getName().equals(descriptor.getName())) {
continue;
}
final LookupStrategy parentFirst = getClassLoaderLookupStrategy(descriptor, dependencyPluginDescriptor);
for (String exportedPackage : dependencyPluginDescriptor.getClassLoaderModel().getExportedPackages()) {
pluginsLookupPolicies.put(exportedPackage, parentFirst);
}
}
ContainerOnlyLookupStrategy containerOnlyLookupStrategy = new ContainerOnlyLookupStrategy(this.getClass().getClassLoader());
for (MuleModule module : moduleRepository.getModules()) {
if (module.getPrivilegedArtifacts().contains(descriptor.getName())) {
for (String packageName : module.getPrivilegedExportedPackages()) {
pluginsLookupPolicies.put(packageName, containerOnlyLookupStrategy);
}
}
}
final ClassLoaderLookupPolicy lookupPolicy = baseLookupPolicy.extend(pluginsLookupPolicies);
return new MuleArtifactClassLoader(artifactId, descriptor, descriptor.getClassLoaderModel().getUrls(), parent, lookupPolicy);
}
private LookupStrategy getClassLoaderLookupStrategy(ArtifactPluginDescriptor descriptor,
ArtifactPluginDescriptor dependencyPluginDescriptor) {
final LookupStrategy parentFirst;
if (isDependencyPlugin(descriptor.getClassLoaderModel().getDependencies(), dependencyPluginDescriptor)) {
parentFirst = PARENT_FIRST;
} else {
parentFirst = CHILD_ONLY;
}
return parentFirst;
}
private boolean isDependencyPlugin(Set<BundleDependency> pluginDependencies,
ArtifactPluginDescriptor dependencyPluginDescriptor) {
for (BundleDependency pluginDependency : pluginDependencies) {
if (pluginDependency.getDescriptor().getArtifactId()
.equals(dependencyPluginDescriptor.getBundleDescriptor().getArtifactId())
&& MULE_PLUGIN_CLASSIFIER.equals(pluginDependency.getDescriptor().getClassifier().get())) {
return true;
}
}
return false;
}
}