/*
* 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.module.deployment.impl.internal.policy;
import static java.io.File.separator;
import static java.lang.String.format;
import static org.mule.runtime.api.util.Preconditions.checkArgument;
import static org.mule.runtime.core.config.bootstrap.ArtifactType.POLICY;
import static org.mule.runtime.deployment.model.api.policy.PolicyTemplateDescriptor.META_INF;
import static org.mule.runtime.deployment.model.api.policy.PolicyTemplateDescriptor.MULE_ARTIFACT;
import static org.mule.runtime.deployment.model.api.policy.PolicyTemplateDescriptor.MULE_POLICY_JSON;
import org.mule.runtime.api.deployment.meta.MuleArtifactLoaderDescriptor;
import org.mule.runtime.api.deployment.meta.MulePolicyModel;
import org.mule.runtime.api.deployment.persistence.MulePolicyModelJsonSerializer;
import org.mule.runtime.api.exception.MuleRuntimeException;
import org.mule.runtime.core.registry.SpiServiceRegistry;
import org.mule.runtime.deployment.model.api.plugin.ArtifactPluginDescriptor;
import org.mule.runtime.deployment.model.api.policy.PolicyTemplateDescriptor;
import org.mule.runtime.module.artifact.descriptor.ArtifactDescriptorCreateException;
import org.mule.runtime.module.artifact.descriptor.ArtifactDescriptorFactory;
import org.mule.runtime.module.artifact.descriptor.BundleDependency;
import org.mule.runtime.module.artifact.descriptor.BundleDescriptor;
import org.mule.runtime.module.artifact.descriptor.BundleDescriptorLoader;
import org.mule.runtime.module.artifact.descriptor.ClassLoaderModel;
import org.mule.runtime.module.artifact.descriptor.ClassLoaderModelLoader;
import org.mule.runtime.module.artifact.descriptor.InvalidDescriptorLoaderException;
import org.mule.runtime.module.deployment.impl.internal.artifact.DescriptorLoaderRepository;
import org.mule.runtime.module.deployment.impl.internal.artifact.LoaderNotFoundException;
import org.mule.runtime.module.deployment.impl.internal.artifact.ServiceRegistryDescriptorLoaderRepository;
import org.mule.runtime.module.deployment.impl.internal.plugin.ArtifactPluginDescriptorFactory;
import org.mule.runtime.module.deployment.impl.internal.plugin.ArtifactPluginDescriptorLoader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.io.IOUtils;
/**
* Creates descriptors for policy templates
*/
public class PolicyTemplateDescriptorFactory implements ArtifactDescriptorFactory<PolicyTemplateDescriptor> {
protected static final String MISSING_POLICY_DESCRIPTOR_ERROR = "Policy must contain a " + MULE_POLICY_JSON + " file";
private final ArtifactPluginDescriptorLoader artifactPluginDescriptorLoader;
private final DescriptorLoaderRepository descriptorLoaderRepository;
/**
* Creates a default factory
*/
@SuppressWarnings({"unused"})
public PolicyTemplateDescriptorFactory() {
this(new ArtifactPluginDescriptorLoader(new ArtifactPluginDescriptorFactory()),
new ServiceRegistryDescriptorLoaderRepository(new SpiServiceRegistry()));
}
/**
* Creates a new factory
*
* @param artifactPluginDescriptorLoader loads the artifact descriptor for plugins used on the policy template. Non null
* @param descriptorLoaderRepository contains all the {@link ClassLoaderModelLoader} registered on the container. Non null
*/
public PolicyTemplateDescriptorFactory(ArtifactPluginDescriptorLoader artifactPluginDescriptorLoader,
DescriptorLoaderRepository descriptorLoaderRepository) {
checkArgument(artifactPluginDescriptorLoader != null, "artifactPluginDescriptorLoader cannot be null");
checkArgument(descriptorLoaderRepository != null, "descriptorLoaderRepository cannot be null");
this.artifactPluginDescriptorLoader = artifactPluginDescriptorLoader;
this.descriptorLoaderRepository = descriptorLoaderRepository;
}
@Override
public PolicyTemplateDescriptor create(File artifactFolder) throws ArtifactDescriptorCreateException {
final File policyJsonFile = new File(artifactFolder, META_INF + separator + MULE_ARTIFACT + separator + MULE_POLICY_JSON);
if (!policyJsonFile.exists()) {
throw new ArtifactDescriptorCreateException(MISSING_POLICY_DESCRIPTOR_ERROR);
}
final MulePolicyModel mulePolicyModel = getMulePolicyJsonDescriber(policyJsonFile);
final PolicyTemplateDescriptor descriptor = new PolicyTemplateDescriptor(mulePolicyModel.getName());
descriptor.setRootFolder(artifactFolder);
if (mulePolicyModel.getClassLoaderModelLoaderDescriptor().isPresent()) {
descriptor.setClassLoaderModel(getClassLoaderModel(artifactFolder, mulePolicyModel));
}
descriptor.setBundleDescriptor(getBundleDescriptor(artifactFolder, mulePolicyModel));
descriptor.setPlugins(parseArtifactPluginDescriptors(descriptor));
return descriptor;
}
private BundleDescriptor getBundleDescriptor(File artifactFolder, MulePolicyModel mulePolicyModel) {
BundleDescriptorLoader bundleDescriptorLoader;
try {
bundleDescriptorLoader =
descriptorLoaderRepository.get(mulePolicyModel.getBundleDescriptorLoader().getId(), POLICY,
BundleDescriptorLoader.class);
} catch (LoaderNotFoundException e) {
throw new ArtifactDescriptorCreateException(invalidBundleDescriptorLoaderIdError(mulePolicyModel
.getBundleDescriptorLoader()));
}
try {
return bundleDescriptorLoader.load(artifactFolder,
mulePolicyModel.getBundleDescriptorLoader().getAttributes(), POLICY);
} catch (InvalidDescriptorLoaderException e) {
throw new ArtifactDescriptorCreateException(e);
}
}
private ClassLoaderModel getClassLoaderModel(File artifactFolder, MulePolicyModel mulePolicyModel) {
MuleArtifactLoaderDescriptor muleArtifactLoaderDescriptor = mulePolicyModel.getClassLoaderModelLoaderDescriptor().get();
ClassLoaderModelLoader classLoaderModelLoader;
try {
classLoaderModelLoader =
descriptorLoaderRepository.get(muleArtifactLoaderDescriptor.getId(), POLICY, ClassLoaderModelLoader.class);
} catch (LoaderNotFoundException e) {
throw new ArtifactDescriptorCreateException(invalidClassLoaderModelIdError(muleArtifactLoaderDescriptor));
}
try {
return classLoaderModelLoader
.load(artifactFolder, mulePolicyModel.getClassLoaderModelLoaderDescriptor().get().getAttributes(), POLICY);
} catch (InvalidDescriptorLoaderException e) {
throw new ArtifactDescriptorCreateException(e);
}
}
protected static String invalidBundleDescriptorLoaderIdError(MuleArtifactLoaderDescriptor bundleDescriptorLoader) {
return "Unknown bundle descriptor loader: " + bundleDescriptorLoader.getId();
}
protected static String invalidClassLoaderModelIdError(MuleArtifactLoaderDescriptor muleArtifactLoaderDescriptor) {
return "Unknown model loader: " + muleArtifactLoaderDescriptor.getId();
}
private Set<ArtifactPluginDescriptor> parseArtifactPluginDescriptors(PolicyTemplateDescriptor descriptor) {
Set<BundleDependency> pluginDependencies = descriptor.getClassLoaderModel().getDependencies().stream()
.filter(dependency -> dependency.getDescriptor().isPlugin()).collect(Collectors.toSet());
return pluginDependencies.stream().map(dependency -> {
try {
return artifactPluginDescriptorLoader.load(new File(dependency.getBundleUrl().getFile()));
} catch (IOException e) {
throw new MuleRuntimeException(e);
}
}).collect(Collectors.toSet());
}
private MulePolicyModel getMulePolicyJsonDescriber(File jsonFile) {
try (InputStream stream = new FileInputStream(jsonFile)) {
return new MulePolicyModelJsonSerializer().deserialize(IOUtils.toString(stream));
} catch (IOException e) {
throw new IllegalArgumentException(format("Could not read extension describer on plugin '%s'", jsonFile.getAbsolutePath()),
e);
}
}
}