/* * 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.plugin; import static java.lang.String.format; import static org.mule.runtime.api.util.Preconditions.checkArgument; import static org.mule.runtime.core.config.bootstrap.ArtifactType.PLUGIN; import static org.mule.runtime.core.util.JarUtils.loadFileContentFrom; import static org.mule.runtime.deployment.model.api.plugin.ArtifactPluginDescriptor.MULE_ARTIFACT_PATH_INSIDE_JAR; import static org.mule.runtime.deployment.model.api.plugin.ArtifactPluginDescriptor.MULE_PLUGIN_JSON; import org.mule.runtime.api.deployment.meta.MuleArtifactLoaderDescriptor; import org.mule.runtime.api.deployment.meta.MulePluginModel; import org.mule.runtime.api.deployment.persistence.MulePluginModelJsonSerializer; import org.mule.runtime.core.registry.SpiServiceRegistry; import org.mule.runtime.deployment.model.api.plugin.ArtifactPluginDescriptor; import org.mule.runtime.deployment.model.api.plugin.LoaderDescriber; import org.mule.runtime.module.artifact.descriptor.ArtifactDescriptorCreateException; import org.mule.runtime.module.artifact.descriptor.ArtifactDescriptorFactory; 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 java.io.File; import java.io.IOException; import java.util.Optional; /** * Creates {@link ArtifactPluginDescriptor} instances */ public class ArtifactPluginDescriptorFactory implements ArtifactDescriptorFactory<ArtifactPluginDescriptor> { private final DescriptorLoaderRepository descriptorLoaderRepository; /** * Creates a default factory */ public ArtifactPluginDescriptorFactory() { this(new ServiceRegistryDescriptorLoaderRepository(new SpiServiceRegistry())); } /** * Creates a custom factory * * @param descriptorLoaderRepository contains all the {@link ClassLoaderModelLoader} registered on the container. Non null */ public ArtifactPluginDescriptorFactory(DescriptorLoaderRepository descriptorLoaderRepository) { checkArgument(descriptorLoaderRepository != null, "descriptorLoaderRepository cannot be null"); this.descriptorLoaderRepository = descriptorLoaderRepository; } @Override public ArtifactPluginDescriptor create(File pluginJarFile) throws ArtifactDescriptorCreateException { try { checkArgument(pluginJarFile.isDirectory() || pluginJarFile.getName().endsWith(".jar"), "provided file is not a plugin: " + pluginJarFile.getAbsolutePath()); // Use / instead of File.separator as the file is going to be accessed inside the jar as a URL String mulePluginJsonPathInsideJarFile = MULE_ARTIFACT_PATH_INSIDE_JAR + "/" + MULE_PLUGIN_JSON; Optional<byte[]> jsonDescriptorContentOptional = loadFileContentFrom(pluginJarFile, mulePluginJsonPathInsideJarFile); return jsonDescriptorContentOptional .map(jsonDescriptorContent -> loadFromJsonDescriptor(pluginJarFile, new String(jsonDescriptorContent))) .orElseThrow(() -> new ArtifactDescriptorCreateException(pluginDescriptorNotFound(pluginJarFile, mulePluginJsonPathInsideJarFile))); } catch (ArtifactDescriptorCreateException e) { throw e; } catch (IOException e) { throw new ArtifactDescriptorCreateException(e); } } private ArtifactPluginDescriptor loadFromJsonDescriptor(File pluginJarFile, String jsonDescriptorContent) { final MulePluginModel mulePluginModel = getMulePluginJsonDescriber(jsonDescriptorContent); final ArtifactPluginDescriptor descriptor = new ArtifactPluginDescriptor(mulePluginModel.getName()); mulePluginModel.getClassLoaderModelLoaderDescriptor().ifPresent(classLoaderModelLoaderDescriptor -> { descriptor.setClassLoaderModel(getClassLoaderModel(pluginJarFile, classLoaderModelLoaderDescriptor)); }); descriptor.setBundleDescriptor(getBundleDescriptor(pluginJarFile, mulePluginModel)); mulePluginModel.getExtensionModelLoaderDescriptor().ifPresent(extensionModelDescriptor -> { final LoaderDescriber loaderDescriber = new LoaderDescriber(extensionModelDescriptor.getId()); loaderDescriber.addAttributes(extensionModelDescriptor.getAttributes()); descriptor.setExtensionModelDescriptorProperty(loaderDescriber); }); return descriptor; } private BundleDescriptor getBundleDescriptor(File pluginFolder, MulePluginModel mulePluginModel) { BundleDescriptorLoader bundleDescriptorLoader; try { bundleDescriptorLoader = descriptorLoaderRepository.get(mulePluginModel.getBundleDescriptorLoader().getId(), PLUGIN, BundleDescriptorLoader.class); } catch (LoaderNotFoundException e) { throw new ArtifactDescriptorCreateException(invalidBundleDescriptorLoaderIdError(pluginFolder, mulePluginModel .getBundleDescriptorLoader())); } try { return bundleDescriptorLoader.load(pluginFolder, mulePluginModel.getBundleDescriptorLoader().getAttributes(), PLUGIN); } catch (InvalidDescriptorLoaderException e) { throw new ArtifactDescriptorCreateException(e); } } private ClassLoaderModel getClassLoaderModel(File pluginJarFile, MuleArtifactLoaderDescriptor classLoaderModelLoaderDescriptor) { ClassLoaderModelLoader classLoaderModelLoader; try { classLoaderModelLoader = descriptorLoaderRepository.get(classLoaderModelLoaderDescriptor.getId(), PLUGIN, ClassLoaderModelLoader.class); } catch (LoaderNotFoundException e) { throw new ArtifactDescriptorCreateException(invalidClassLoaderModelIdError(pluginJarFile, classLoaderModelLoaderDescriptor)); } final ClassLoaderModel classLoaderModel; try { classLoaderModel = classLoaderModelLoader.load(pluginJarFile, classLoaderModelLoaderDescriptor.getAttributes(), PLUGIN); } catch (InvalidDescriptorLoaderException e) { throw new ArtifactDescriptorCreateException(e); } return classLoaderModel; } protected static String pluginDescriptorNotFound(File pluginFile, String mulePluginJsonPathInsideJarFile) { return format("The plugin descriptor '%s' on plugin file '%s' is not present", mulePluginJsonPathInsideJarFile, pluginFile); } protected static String invalidBundleDescriptorLoaderIdError(File pluginFolder, MuleArtifactLoaderDescriptor bundleDescriptorLoader) { return format("The identifier '%s' for a bundle descriptor loader is not supported (error found while reading plugin '%s')", bundleDescriptorLoader.getId(), pluginFolder.getAbsolutePath()); } protected static String invalidClassLoaderModelIdError(File pluginFolder, MuleArtifactLoaderDescriptor classLoaderModelLoaderDescriptor) { return format("The identifier '%s' for a class loader model descriptor is not supported (error found while reading plugin '%s')", classLoaderModelLoaderDescriptor.getId(), pluginFolder.getAbsolutePath()); } private MulePluginModel getMulePluginJsonDescriber(String jsonDescriptorContent) { return new MulePluginModelJsonSerializer().deserialize(jsonDescriptorContent); } }