/* * 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.application; import static java.lang.Integer.compare; import static java.lang.String.format; import static java.util.Optional.of; import static org.mule.runtime.api.util.Preconditions.checkArgument; import org.mule.runtime.api.lifecycle.Disposable; import org.mule.runtime.core.policy.Policy; import org.mule.runtime.core.policy.PolicyParametrization; import org.mule.runtime.core.policy.PolicyProvider; import org.mule.runtime.deployment.model.api.application.Application; import org.mule.runtime.deployment.model.api.policy.PolicyRegistrationException; import org.mule.runtime.deployment.model.api.policy.PolicyTemplate; import org.mule.runtime.deployment.model.api.policy.PolicyTemplateDescriptor; import org.mule.runtime.module.deployment.impl.internal.policy.ApplicationPolicyInstance; import org.mule.runtime.module.deployment.impl.internal.policy.PolicyInstanceProviderFactory; import org.mule.runtime.module.deployment.impl.internal.policy.PolicyTemplateFactory; import org.mule.runtime.policy.api.PolicyPointcutParameters; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Optional; /** * Provides policy management and provision for Mule applications */ public class MuleApplicationPolicyProvider implements ApplicationPolicyProvider, PolicyProvider, Disposable { private final PolicyTemplateFactory policyTemplateFactory; private final PolicyInstanceProviderFactory policyInstanceProviderFactory; private final List<RegisteredPolicyTemplate> registeredPolicyTemplates = new LinkedList<>(); private final List<RegisteredPolicyInstanceProvider> registeredPolicyInstanceProviders = new LinkedList<>(); private Application application; /** * Creates a new provider * * @param policyTemplateFactory used to create the policy templates for the application. Non null. * @param policyInstanceProviderFactory used to create the policy instances for the application. Non null. */ public MuleApplicationPolicyProvider(PolicyTemplateFactory policyTemplateFactory, PolicyInstanceProviderFactory policyInstanceProviderFactory) { this.policyTemplateFactory = policyTemplateFactory; this.policyInstanceProviderFactory = policyInstanceProviderFactory; } @Override public synchronized void addPolicy(PolicyTemplateDescriptor policyTemplateDescriptor, PolicyParametrization parametrization) throws PolicyRegistrationException { try { checkArgument(application != null, "application was not configured on the policy provider"); Optional<RegisteredPolicyInstanceProvider> registeredPolicyInstanceProvider = registeredPolicyInstanceProviders.stream() .filter(p -> p.getPolicyId().equals(parametrization.getId())).findFirst(); if (registeredPolicyInstanceProvider.isPresent()) { throw new IllegalArgumentException(createPolicyAlreadyRegisteredError(parametrization.getId())); } Optional<RegisteredPolicyTemplate> registeredPolicyTemplate = registeredPolicyTemplates.stream() .filter(p -> p.policyTemplate.getDescriptor().getBundleDescriptor().getArtifactId() .equals(policyTemplateDescriptor.getBundleDescriptor().getArtifactId())) .findAny(); if (!registeredPolicyTemplate.isPresent()) { PolicyTemplate policyTemplate = policyTemplateFactory.createArtifact(application, policyTemplateDescriptor); registeredPolicyTemplate = of(new RegisteredPolicyTemplate(policyTemplate)); registeredPolicyTemplates.add(registeredPolicyTemplate.get()); } ApplicationPolicyInstance applicationPolicyInstance = policyInstanceProviderFactory .create(application, registeredPolicyTemplate.get().policyTemplate, parametrization); applicationPolicyInstance.initialise(); registeredPolicyInstanceProviders .add(new RegisteredPolicyInstanceProvider(applicationPolicyInstance, parametrization.getId())); registeredPolicyInstanceProviders.sort(null); registeredPolicyTemplate.get().count++; } catch (Exception e) { throw new PolicyRegistrationException(createPolicyRegistrationError(parametrization.getId()), e); } } @Override public synchronized boolean removePolicy(String parametrizedPolicyId) { Optional<RegisteredPolicyInstanceProvider> registeredPolicyInstanceProvider = registeredPolicyInstanceProviders.stream() .filter(p -> p.getPolicyId().equals(parametrizedPolicyId)).findFirst(); registeredPolicyInstanceProvider.ifPresent(provider -> { provider.getApplicationPolicyInstance().dispose(); registeredPolicyInstanceProviders.remove(provider); Optional<RegisteredPolicyTemplate> registeredPolicyTemplate = registeredPolicyTemplates.stream() .filter(p -> p.policyTemplate.equals(p.policyTemplate)) .findFirst(); if (!registeredPolicyTemplate.isPresent()) { throw new IllegalStateException("Cannot find registered policy template"); } registeredPolicyTemplate.get().count--; if (registeredPolicyTemplate.get().count == 0) { application.getRegionClassLoader() .removeClassLoader(registeredPolicyTemplate.get().policyTemplate.getArtifactClassLoader()); registeredPolicyTemplate.get().policyTemplate.dispose(); registeredPolicyTemplates.remove(registeredPolicyTemplate.get()); } }); return registeredPolicyInstanceProvider.isPresent(); } @Override public List<Policy> findSourceParameterizedPolicies(PolicyPointcutParameters policyPointcutParameters) { List<Policy> policies = new ArrayList<>(); if (!registeredPolicyInstanceProviders.isEmpty()) { for (RegisteredPolicyInstanceProvider registeredPolicyInstanceProvider : registeredPolicyInstanceProviders) { if (registeredPolicyInstanceProvider.getApplicationPolicyInstance().getPointcut().matches(policyPointcutParameters)) { if (registeredPolicyInstanceProvider.getApplicationPolicyInstance().getSourcePolicy().isPresent()) { policies.add(registeredPolicyInstanceProvider.getApplicationPolicyInstance().getSourcePolicy().get()); } } } } return policies; } @Override public List<Policy> findOperationParameterizedPolicies(PolicyPointcutParameters policyPointcutParameters) { List<Policy> policies = new ArrayList<>(); if (!registeredPolicyInstanceProviders.isEmpty()) { for (RegisteredPolicyInstanceProvider registeredPolicyInstanceProvider : registeredPolicyInstanceProviders) { if (registeredPolicyInstanceProvider.getApplicationPolicyInstance().getPointcut().matches(policyPointcutParameters)) { if (registeredPolicyInstanceProvider.getApplicationPolicyInstance().getOperationPolicy().isPresent()) { policies.add(registeredPolicyInstanceProvider.getApplicationPolicyInstance().getOperationPolicy().get()); } } } } return policies; } @Override public void dispose() { for (RegisteredPolicyInstanceProvider registeredPolicyInstanceProvider : registeredPolicyInstanceProviders) { registeredPolicyInstanceProvider.getApplicationPolicyInstance().dispose(); } registeredPolicyInstanceProviders.clear(); for (RegisteredPolicyTemplate registeredPolicyTemplate : registeredPolicyTemplates) { try { registeredPolicyTemplate.policyTemplate.dispose(); } catch (RuntimeException e) { // Ignore and continue } registeredPolicyTemplates.clear(); } } public void setApplication(Application application) { this.application = application; } static String createPolicyAlreadyRegisteredError(String policyId) { return format("Policy already registered: '%s'", policyId); } static String createPolicyRegistrationError(String policyId) { return format("Error occured registering policy '%s'", policyId); } private static class RegisteredPolicyTemplate { private volatile int count; private final PolicyTemplate policyTemplate; private RegisteredPolicyTemplate(PolicyTemplate policyTemplate) { this.policyTemplate = policyTemplate; } } private static class RegisteredPolicyInstanceProvider implements Comparable<RegisteredPolicyInstanceProvider> { private final ApplicationPolicyInstance applicationPolicyInstance; private final String policyId; public RegisteredPolicyInstanceProvider(ApplicationPolicyInstance applicationPolicyInstance, String policyId) { this.applicationPolicyInstance = applicationPolicyInstance; this.policyId = policyId; } @Override public int compareTo(RegisteredPolicyInstanceProvider registeredPolicyInstanceProvider) { return compare(applicationPolicyInstance.getOrder(), registeredPolicyInstanceProvider.applicationPolicyInstance.getOrder()); } public ApplicationPolicyInstance getApplicationPolicyInstance() { return applicationPolicyInstance; } public String getPolicyId() { return policyId; } } }