All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mule.module.launcher.domain.DefaultMuleDomain Maven / Gradle / Ivy

There is a newer version: 3.9.0
Show newest version
/*
 * 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.module.launcher.domain;

import static org.mule.util.SplashScreen.miniSplash;
import org.mule.MuleServer;
import org.mule.api.MuleContext;
import org.mule.api.MuleException;
import org.mule.api.MuleRuntimeException;
import org.mule.api.config.ConfigurationBuilder;
import org.mule.api.config.DomainMuleContextAwareConfigurationBuilder;
import org.mule.api.lifecycle.InitialisationException;
import org.mule.config.builders.AutoConfigurationBuilder;
import org.mule.config.i18n.CoreMessages;
import org.mule.context.DefaultMuleContextFactory;
import org.mule.module.launcher.DeploymentInitException;
import org.mule.module.launcher.DeploymentListener;
import org.mule.module.launcher.DeploymentStartException;
import org.mule.module.launcher.DeploymentStopException;
import org.mule.module.launcher.MuleDeploymentService;
import org.mule.module.launcher.application.Application;
import org.mule.module.launcher.application.NullDeploymentListener;
import org.mule.module.launcher.artifact.ArtifactClassLoader;
import org.mule.module.launcher.artifact.MuleContextDeploymentListener;
import org.mule.module.launcher.descriptor.ApplicationDescriptor;
import org.mule.module.launcher.descriptor.DomainDescriptor;
import org.mule.util.ClassUtils;
import org.mule.util.ExceptionUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class DefaultMuleDomain implements Domain
{

    protected transient final Log logger = LogFactory.getLog(getClass());
    protected transient final Log deployLogger = LogFactory.getLog(MuleDeploymentService.class);

    private final DomainClassLoaderRepository domainClassLoaderRepository;
    private final DomainDescriptor descriptor;
    private MuleContext muleContext;
    private DeploymentListener deploymentListener;
    private ArtifactClassLoader deploymentClassLoader;

    private File configResourceFile;

    public DefaultMuleDomain(DomainClassLoaderRepository domainClassLoaderRepository, DomainDescriptor descriptor)
    {
        this.domainClassLoaderRepository = domainClassLoaderRepository;
        this.deploymentListener = new NullDeploymentListener();
        this.descriptor = descriptor;
        refreshClassLoaderAndLoadConfigResourceFile();
    }

    private void refreshClassLoaderAndLoadConfigResourceFile(){
        this.deploymentClassLoader = domainClassLoaderRepository.getDomainClassLoader(descriptor);
        URL resource = deploymentClassLoader.findLocalResource(DOMAIN_CONFIG_FILE_LOCATION);
        if (resource != null)
        {
            try
            {
                this.configResourceFile = new File(URLDecoder.decode(resource.getFile(), "UTF-8"));
            }
            catch (UnsupportedEncodingException e)
            {
                throw new RuntimeException("Unable to find config resource file: " + resource.getFile());
            }
        }
    }

    public void setDeploymentListener(DeploymentListener deploymentListener)
    {
        this.deploymentListener = deploymentListener;
    }

    public String getName()
    {
        return descriptor.getName();
    }

    @Override
    public MuleContext getMuleContext()
    {
        return muleContext;
    }

    @Override
    public ConfigurationBuilder createApplicationConfigurationBuilder(Application application) throws Exception
    {
        String configBuilderClassName = determineConfigBuilderClassNameForApplication(application);
        ConfigurationBuilder configurationBuilder = (ConfigurationBuilder) ClassUtils.instanciateClass(configBuilderClassName,
                                                                                                       new Object[] {application.getDescriptor().getAbsoluteResourcePaths()}, application.getArtifactClassLoader().getClassLoader());

        if (!containsSharedResources())
        {
            return configurationBuilder;
        }
        else
        {
            if (configurationBuilder instanceof DomainMuleContextAwareConfigurationBuilder)
            {
                ((DomainMuleContextAwareConfigurationBuilder) configurationBuilder).setDomainContext(getMuleContext());
            }
            else
            {
                throw new MuleRuntimeException(CoreMessages.createStaticMessage(String.format("ConfigurationBuilder %s does not support domain context", configurationBuilder.getClass().getCanonicalName())));
            }
            return configurationBuilder;
        }
    }

    protected String determineConfigBuilderClassNameForApplication(Application defaultMuleApplication)
    {
        // Provide a shortcut for Spring: "-builder spring"
        final String builderFromDesc = defaultMuleApplication.getDescriptor().getConfigurationBuilder();
        if ("spring".equalsIgnoreCase(builderFromDesc))
        {
            return ApplicationDescriptor.CLASSNAME_SPRING_CONFIG_BUILDER;
        }
        else if (builderFromDesc == null)
        {
            return AutoConfigurationBuilder.class.getName();
        }
        else
        {
            return builderFromDesc;
        }
    }

    @Override
    public void install()
    {
        if (logger.isInfoEnabled())
        {
            logger.info(miniSplash(String.format("New domain '%s'", getArtifactName())));
        }
        refreshClassLoaderAndLoadConfigResourceFile();
    }


    @Override
    public void init()
    {
        if (logger.isInfoEnabled())
        {
            logger.info(miniSplash(String.format("Initializing domain '%s'", getArtifactName())));
        }

        try
        {
            if (this.configResourceFile != null)
            {
                validateConfigurationFileDoNotUsesCoreNamespace();

                ConfigurationBuilder cfgBuilder = createConfigurationBuilder();
                if (!cfgBuilder.isConfigured())
                {
                    List builders = new ArrayList(3);

                    // We need to add this builder before spring so that we can use Mule annotations in Spring or any other builder
                    addAnnotationsConfigBuilderIfPresent(builders);

                    builders.add(cfgBuilder);

                    DefaultMuleContextFactory muleContextFactory = new DefaultMuleContextFactory();
                    if (deploymentListener != null)
                    {
                        muleContextFactory.addListener(new MuleContextDeploymentListener(getArtifactName(), deploymentListener));
                    }
                    DomainMuleContextBuilder domainMuleContextBuilder = new DomainMuleContextBuilder(descriptor.getName());
                    muleContext = muleContextFactory.createMuleContext(builders, domainMuleContextBuilder);
                }
            }
        }
        catch (Exception e)
        {
            // log it here so it ends up in app log, sys log will only log a message without stacktrace
            logger.error(null, ExceptionUtils.getRootCause(e));
            throw new DeploymentInitException(CoreMessages.createStaticMessage(ExceptionUtils.getRootCauseMessage(e)), e);
        }
    }

    private void validateConfigurationFileDoNotUsesCoreNamespace() throws FileNotFoundException
    {
        Scanner scanner = null;
        try
        {
            scanner = new Scanner(configResourceFile);
            while (scanner.hasNextLine())
            {
                final String lineFromFile = scanner.nextLine();
                if (lineFromFile.contains(" builders) throws Exception
    {
        // If the annotations module is on the classpath, add the annotations config builder to
        // the list. This will enable annotations config for this instance.
        if (ClassUtils.isClassOnPath(MuleServer.CLASSNAME_ANNOTATIONS_CONFIG_BUILDER, getClass()))
        {
            Object configBuilder = ClassUtils.instanciateClass(
                    MuleServer.CLASSNAME_ANNOTATIONS_CONFIG_BUILDER, ClassUtils.NO_ARGS, getClass());
            builders.add((ConfigurationBuilder) configBuilder);
        }
    }

    private ConfigurationBuilder createConfigurationBuilder()
    {
        try
        {
            return (ConfigurationBuilder) ClassUtils.instanciateClass("org.mule.config.spring.SpringXmlDomainConfigurationBuilder",
                                                                      new Object[] {getResourceFiles()[0].getName()}, deploymentClassLoader.getClassLoader());
        }
        catch (Exception e)
        {
            throw new MuleRuntimeException(e);
        }
    }

    @Override
    public void start()
    {
        try
        {
            if (this.muleContext != null)
            {
                try
                {
                    this.muleContext.start();
                }
                catch (MuleException e)
                {
                    logger.error(null, ExceptionUtils.getRootCause(e));
                    throw new DeploymentStartException(CoreMessages.createStaticMessage(ExceptionUtils.getRootCauseMessage(e)), e);
                }
            }
            // null CCL ensures we log at 'system' level
            // TODO create a more usable wrapper for any logger to be logged at sys level
            final ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
            try
            {
                Thread.currentThread().setContextClassLoader(null);
                deployLogger.info(miniSplash(String.format("Started domain '%s'", getArtifactName())));
            }
            finally
            {
                Thread.currentThread().setContextClassLoader(oldCl);
            }
        }
        catch (Exception e)
        {
            throw new DeploymentStartException(CoreMessages.createStaticMessage("Failure trying to start domain " + getArtifactName()), e);
        }
    }

    @Override
    public void stop()
    {
        try
        {
            if (logger.isInfoEnabled())
            {
                logger.info(miniSplash(String.format("Stopping domain '%s'", getArtifactName())));
            }
            if (this.muleContext != null)
            {
                this.muleContext.stop();
            }
        }
        catch (Exception e)
        {
            throw new DeploymentStopException(CoreMessages.createStaticMessage("Failure trying to stop domain " + getArtifactName()), e);
        }
    }

    @Override
    public void dispose()
    {
        if (logger.isInfoEnabled())
        {
            logger.info(miniSplash(String.format("Disposing domain '%s'", getArtifactName())));
        }
        if (this.muleContext != null)
        {
            this.muleContext.dispose();
        }
        this.deploymentClassLoader.dispose();
    }

    @Override
    public String getArtifactName()
    {
        return descriptor.getName();
    }

    @Override
    public DomainDescriptor getDescriptor()
    {
        return descriptor;
    }

    @Override
    public File[] getResourceFiles()
    {
        return configResourceFile == null ? new File[0] : new File[] {configResourceFile};
    }

    @Override
    public ArtifactClassLoader getArtifactClassLoader()
    {
        return deploymentClassLoader;
    }

    public void initialise()
    {
        try
        {
            if (this.muleContext != null)
            {
                this.muleContext.initialise();
            }
        }
        catch (InitialisationException e)
        {
            throw new DeploymentInitException(CoreMessages.createStaticMessage("Failure trying to initialise domain " + getArtifactName()), e);
        }
    }

    public boolean containsSharedResources()
    {
        return this.muleContext != null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy