Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.config.internal;
import static java.lang.String.format;
import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.mule.runtime.api.i18n.I18nMessageFactory.createStaticMessage;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
import org.mule.runtime.api.exception.DefaultMuleException;
import org.mule.runtime.api.exception.MuleException;
import org.mule.runtime.api.exception.MuleRuntimeException;
import org.mule.runtime.api.lifecycle.InitialisationException;
import org.mule.runtime.api.lifecycle.LifecycleException;
import org.mule.runtime.config.internal.dsl.model.ConfigurationDependencyResolver;
import org.mule.runtime.config.internal.factories.ConstantFactoryBean;
import org.mule.runtime.core.api.Injector;
import org.mule.runtime.core.api.MuleContext;
import org.mule.runtime.core.api.lifecycle.LifecycleManager;
import org.mule.runtime.core.api.util.StringUtils;
import org.mule.runtime.core.api.util.func.CheckedRunnable;
import org.mule.runtime.core.internal.lifecycle.LifecycleInterceptor;
import org.mule.runtime.core.internal.lifecycle.phases.NotInLifecyclePhase;
import org.mule.runtime.core.internal.registry.AbstractRegistry;
import org.mule.runtime.core.internal.registry.LifecycleRegistry;
import org.mule.runtime.core.privileged.registry.RegistrationException;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
public class SpringRegistry extends AbstractRegistry implements LifecycleRegistry, Injector {
public static final String REGISTRY_ID = "org.mule.Registry.Spring";
/**
* Key used to lookup Spring Application Context from SpringRegistry via Mule's Registry interface.
*/
public static final String SPRING_APPLICATION_CONTEXT = "springApplicationContext";
private BeanDependencyResolver beanDependencyResolver;
protected ApplicationContext applicationContext;
private boolean readOnly;
private RegistrationDelegate registrationDelegate;
// This is used to track the Spring context lifecycle since there is no way to confirm the
// lifecycle phase from the application context
protected AtomicBoolean springContextInitialised = new AtomicBoolean(false);
// Registered objects before the spring registry has been initialised.
private final Map registeredBeanDefinitionsBeforeInitialization = new HashMap<>();
public SpringRegistry(ApplicationContext applicationContext, MuleContext muleContext,
ConfigurationDependencyResolver dependencyResolver,
LifecycleInterceptor lifecycleInterceptor) {
super(REGISTRY_ID, muleContext, lifecycleInterceptor);
setApplicationContext(applicationContext);
this.beanDependencyResolver = new DefaultBeanDependencyResolver(dependencyResolver, this);
}
private void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
if (applicationContext instanceof ConfigurableApplicationContext) {
readOnly = false;
registrationDelegate = new ConfigurableRegistrationDelegate((ConfigurableApplicationContext) applicationContext);
} else {
readOnly = true;
registrationDelegate = new ReadOnlyRegistrationDelegate();
}
}
@Override
protected void doInitialise() throws InitialisationException {
((AbstractApplicationContext) applicationContext)
.addBeanFactoryPostProcessor(createBeforeInitialisationRegisteredObjectsPostProcessor());
// This is used to track the Spring context lifecycle since there is no way to confirm the lifecycle phase from the
// application context
springContextInitialised.set(true);
if (!readOnly) {
((ConfigurableApplicationContext) applicationContext).refresh();
}
}
private BeanDefinitionRegistryPostProcessor createBeforeInitialisationRegisteredObjectsPostProcessor() {
return new BeanDefinitionRegistryPostProcessor() {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registeredBeanDefinitionsBeforeInitialization.entrySet().stream().forEach(beanDefinitionEntry -> {
registry.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());
});
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// do nothing
}
};
}
@Override
public void doDispose() {
// check we aren't trying to close a context which has never been started,
// spring's appContext.isActive() isn't working for this case
if (!springContextInitialised.get()) {
return;
}
if (!isReadOnly() && ((ConfigurableApplicationContext) applicationContext).isActive()) {
((ConfigurableApplicationContext) applicationContext).close();
}
// release the circular implicit ref to MuleContext
applicationContext = null;
this.springContextInitialised.set(false);
}
@Override
protected LifecycleManager createLifecycleManager(LifecycleInterceptor lifecycleInterceptor) {
return new SpringRegistryLifecycleManager(getRegistryId(), this, muleContext, lifecycleInterceptor);
}
/**
* {@inheritDoc}
*
* @return the result of invoking {@link #lookupObject(String, boolean)} with {@code true} as the second argument
*/
@Override
public T lookupObject(String key) {
try {
return (T) lookupObject(key, true);
} catch (NoSuchBeanDefinitionException e) {
return null;
}
}
/**
* If looks for the bean registered under {@code key}. If the returned bean is a prototype and {@code applyLifecycle} is
* {@code true}, then the completed lifecycle phases are applied to the returning bean
*
* @param key the key of the object you're looking for
* @param applyLifecycle if lifecycle should be applied to the returned object. Passing {@code true} doesn't guarantee that the
* lifecycle is applied
* @return object or {@code null} if not found
*/
@SuppressWarnings("unchecked")
@Override
public Object lookupObject(String key, boolean applyLifecycle) {
if (StringUtils.isBlank(key)) {
logger.warn(createStaticMessage("Detected a lookup attempt with an empty or null key").getMessage(),
new Throwable().fillInStackTrace());
return null;
}
if (key.equals(SPRING_APPLICATION_CONTEXT) && applicationContext != null) {
return applicationContext;
} else {
Object object;
try {
object = applicationContext.getBean(key);
} catch (NoSuchBeanDefinitionException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
return null;
}
applyLifecycleIfPrototype(object, key, applyLifecycle);
return object;
}
}
private void applyLifecycleIfPrototype(Object object, String key, boolean applyLifecycle) {
if (applyLifecycle && !isSingleton(key)) {
try {
getLifecycleManager().applyCompletedPhases(object);
} catch (Exception e) {
throw new MuleRuntimeException(createStaticMessage("Could not apply lifecycle into prototype object " + key), e);
}
}
}
@Override
public Collection lookupObjects(Class type) {
return lookupByType(type).values();
}
@Override
public Collection lookupLocalObjects(Class type) {
return internalLookupByTypeWithoutAncestorsAndObjectProviders(type, true, true).values();
}
/**
* For lifecycle we only want spring to return singleton objects from it's application context
*/
@Override
public Collection lookupObjectsForLifecycle(Class type) {
return lookupEntriesForLifecycle(type).values();
}
@Override
public Map lookupByType(Class type) {
return internalLookupByType(type, true, true);
}
@Override
public boolean isSingleton(String key) {
return applicationContext.isSingleton(key);
}
@Override
public void registerObject(String key, Object value) throws RegistrationException {
registrationDelegate.registerObject(key, value);
}
@Override
public void registerObject(String key, Object value, Object metadata) throws RegistrationException {
registrationDelegate.registerObject(key, value, metadata);
}
@Override
public void registerObjects(Map objects) throws RegistrationException {
registrationDelegate.registerObjects(objects);
}
@Override
protected Object doUnregisterObject(String key) throws RegistrationException {
return registrationDelegate.unregisterObject(key);
}
/**
* Will fire any lifecycle methods according to the current lifecycle without actually registering the object in the registry.
* This is useful for prototype objects that are created per request and would clutter the registry with single use objects.
*
* @param object the object to process
* @return the same object with lifecycle methods called (if it has any)
* @throws MuleException if the registry fails to perform the lifecycle change for the object.
*/
@Override
public Object applyLifecycle(Object object) throws MuleException {
getLifecycleManager().applyCompletedPhases(object);
return object;
}
/**
* {@inheritDoc}
*/
@Override
public Object applyLifecycle(Object object, String phase) throws MuleException {
if (phase == null) {
getLifecycleManager().applyCompletedPhases(object);
} else {
getLifecycleManager().applyPhase(object, NotInLifecyclePhase.PHASE_NAME, phase);
}
return object;
}
/**
* {@inheritDoc}
*/
@Override
public void applyLifecycle(Object object, String startPhase, String toPhase) throws MuleException {
getLifecycleManager().applyPhase(object, startPhase, toPhase);
}
/**
* {@inheritDoc}
*/
@Override
public T inject(T object) {
try {
return initialiseObject((ConfigurableApplicationContext) applicationContext, EMPTY, object);
} catch (LifecycleException e) {
throw new MuleRuntimeException(e);
}
}
private T initialiseObject(ConfigurableApplicationContext applicationContext, String key, T object)
throws LifecycleException {
applicationContext.getBeanFactory().autowireBean(object);
T initialised = (T) applicationContext.getBeanFactory().initializeBean(object, key);
return initialised;
}
protected Map internalLookupByType(Class type, boolean nonSingletons, boolean eagerInit) {
try {
Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, type, nonSingletons, eagerInit);
if (nonSingletons && eagerInit) {
beans.forEach((key, value) -> applyLifecycleIfPrototype(value, key, true));
}
return beans;
} catch (FatalBeanException fbex) {
// FBE is a result of a broken config, propagate it (see MULE-3297 for more details)
String message = format("Failed to lookup beans of type %s from the Spring registry", type);
throw new MuleRuntimeException(createStaticMessage(message), fbex);
} catch (Exception e) {
logger.debug(e.getMessage(), e);
return Collections.emptyMap();
}
}
protected Map internalLookupByTypeWithoutAncestorsAndObjectProviders(Class type, boolean nonSingletons,
boolean eagerInit) {
try {
Map beans = ((ObjectProviderAwareBeanFactory) applicationContext.getAutowireCapableBeanFactory())
.getBeansOfTypeWithObjectProviderObjects(type, nonSingletons, eagerInit);
if (nonSingletons && eagerInit) {
beans.forEach((key, value) -> applyLifecycleIfPrototype(value, key, true));
}
return beans;
} catch (FatalBeanException fbex) {
// FBE is a result of a broken config, propagate it (see MULE-3297 for more details)
String message = format("Failed to lookup beans of type %s from the Spring registry", type);
throw new MuleRuntimeException(createStaticMessage(message), fbex);
} catch (Exception e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
return Collections.emptyMap();
}
}
// TODO(pablo.kraan): MULE-12609 - making public to be able to use it from a different package
public Map lookupEntriesForLifecycle(Class type) {
return internalLookupByTypeWithoutAncestorsAndObjectProviders(type, false, false);
}
// TODO(pablo.kraan): MULE-12609 - making public to be able to use it from a different package
public Map getDependencies(String key) {
if (!readOnly) {
Map dependents = new HashMap<>();
for (String dependentKey : ((ConfigurableApplicationContext) applicationContext).getBeanFactory()
.getDependenciesForBean(key)) {
boolean isBeanDefinition =
((ConfigurableApplicationContext) applicationContext).getBeanFactory().containsBeanDefinition(dependentKey);
if (isBeanDefinition && applicationContext.isSingleton(dependentKey)) {
dependents.put(dependentKey, get(dependentKey));
}
}
return dependents;
}
throw new UnsupportedOperationException("This operation is only available when this registry is backed by a ConfigurableApplicationContext");
}
private class ConfigurableRegistrationDelegate implements RegistrationDelegate {
private final ConfigurableApplicationContext applicationContext;
private ConfigurableRegistrationDelegate(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void registerObject(String key, Object value) throws RegistrationException {
try {
muleContext.withLifecycleLock((CheckedRunnable) () -> doRegisterObject(key, value));
} catch (RuntimeException e) {
Throwable cause = e.getCause();
if (cause instanceof RegistrationException) {
throw (RegistrationException) cause;
} else {
throw new RegistrationException(cause);
}
}
}
@Override
public void registerObject(String key, Object value, Object metadata) throws RegistrationException {
registerObject(key, value);
}
@Override
public void registerObjects(Map objects) throws RegistrationException {
if (objects == null || objects.isEmpty()) {
return;
}
for (Map.Entry entry : objects.entrySet()) {
registerObject(entry.getKey(), entry.getValue());
}
}
@Override
public Object unregisterObject(String key) throws RegistrationException {
Object object = applicationContext.getBean(key);
if (applicationContext.getBeanFactory().containsBeanDefinition(key)) {
((BeanDefinitionRegistry) applicationContext.getBeanFactory()).removeBeanDefinition(key);
}
((DefaultListableBeanFactory) applicationContext.getBeanFactory()).destroySingleton(key);
return object;
}
private void doRegisterObject(String key, Object value) throws RegistrationException {
if (springContextInitialised.get()) {
if (applicationContext.containsBean(key)) {
if (logger.isWarnEnabled()) {
logger.warn(
format("Spring registry already contains an object named '%s'. The previous object will be overwritten.",
key));
}
SpringRegistry.this.unregisterObject(key);
}
try {
value = initialiseObject(applicationContext, key, value);
applyLifecycle(value);
applicationContext.getBeanFactory().registerSingleton(key, value);
} catch (Exception e) {
throw new RegistrationException(createStaticMessage("Could not register object for key " + key), e);
}
} else {
// since the context has not yet bean initialized, we register a bean definition instead.
registeredBeanDefinitionsBeforeInitialization.put(key, genericBeanDefinition(ConstantFactoryBean.class)
.addConstructorArgValue(value).getBeanDefinition());
}
}
}
public BeanDependencyResolver getBeanDependencyResolver() {
return beanDependencyResolver;
}
////////////////////////////////////////////////////////////////////////////////////
// Registry meta-data
////////////////////////////////////////////////////////////////////////////////////
@Override
public boolean isReadOnly() {
return readOnly;
}
@Override
public boolean isRemote() {
return false;
}
}