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

com.aspectran.core.context.builder.HybridActivityContextBuilder Maven / Gradle / Ivy

There is a newer version: 8.1.5
Show newest version
/*
 * Copyright (c) 2008-2023 The Aspectran Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.aspectran.core.context.builder;

import com.aspectran.core.adapter.ApplicationAdapter;
import com.aspectran.core.component.Component;
import com.aspectran.core.component.bean.BeanRuleRegistry;
import com.aspectran.core.context.ActivityContext;
import com.aspectran.core.context.env.EnvironmentProfiles;
import com.aspectran.core.context.rule.assistant.ActivityRuleAssistant;
import com.aspectran.core.context.rule.params.AspectranParameters;
import com.aspectran.core.context.rule.parser.ActivityContextParser;
import com.aspectran.core.context.rule.parser.HybridActivityContextParser;
import com.aspectran.core.service.AbstractCoreService;
import com.aspectran.core.util.Assert;
import com.aspectran.core.util.ShutdownHook;
import com.aspectran.core.util.StringUtils;
import com.aspectran.core.util.logging.Logger;
import com.aspectran.core.util.logging.LoggerFactory;

import java.util.concurrent.atomic.AtomicBoolean;

public class HybridActivityContextBuilder extends AbstractActivityContextBuilder {

    private static final Logger logger = LoggerFactory.getLogger(HybridActivityContextBuilder.class);

    private final AbstractCoreService coreService;

    private volatile ActivityContext activityContext;

    /** Flag that indicates whether an ActivityContext is activated */
    private final AtomicBoolean active = new AtomicBoolean();

    /** Synchronization monitor for the "build" and "destroy" */
    private final Object buildDestroyMonitor = new Object();

    /** Reference to the shutdown task, if registered */
    private ShutdownHook.Task shutdownTask;

    public HybridActivityContextBuilder() {
        super();
        this.coreService = null;
    }

    public HybridActivityContextBuilder(AbstractCoreService coreService) {
        super();
        this.coreService = coreService;
        setServiceController(coreService);
    }

    @Override
    public ActivityContext build(AspectranParameters aspectranParameters) throws ActivityContextBuilderException {
        synchronized (this.buildDestroyMonitor) {
            setAspectranParameters(aspectranParameters);
            return doBuild();
        }
    }

    @Override
    public ActivityContext build(String[] contextRules) throws ActivityContextBuilderException {
        synchronized (this.buildDestroyMonitor) {
            setContextRules(contextRules);
            return doBuild();
        }
    }

    @Override
    public ActivityContext build(String contextRuleFile) throws ActivityContextBuilderException {
        synchronized (this.buildDestroyMonitor) {
            setContextRules(new String[] {contextRuleFile});
            return doBuild();
        }
    }

    @Override
    public ActivityContext build() throws ActivityContextBuilderException {
        synchronized (this.buildDestroyMonitor) {
            return doBuild();
        }
    }

    private ActivityContext doBuild() throws ActivityContextBuilderException {
        try {
            Assert.state(!this.active.get(), "ActivityContext is already configured");

            String[] contextRules = getContextRules();
            AspectranParameters aspectranParameters = getAspectranParameters();

            if (contextRules != null) {
                logger.info("Building ActivityContext with context rules [" +
                        StringUtils.joinCommaDelimitedList(contextRules) + "]");
            } else if (aspectranParameters != null) {
                logger.info("Building ActivityContext with specified parameters");
            } else {
                logger.warn("No rootFile or aspectranParameters specified");
            }

            if (getActiveProfiles() != null) {
                logger.info("Activating profiles [" +
                        StringUtils.joinCommaDelimitedList(getActiveProfiles()) + "]");
            }

            if (getDefaultProfiles() != null) {
                logger.info("Default profiles [" +
                        StringUtils.joinCommaDelimitedList(getDefaultProfiles()) + "]");
            }

            long startTime = System.currentTimeMillis();

            ApplicationAdapter applicationAdapter = createApplicationAdapter();
            EnvironmentProfiles environmentProfiles = createEnvironmentProfiles();
            ActivityRuleAssistant assistant = new ActivityRuleAssistant(applicationAdapter, environmentProfiles);
            assistant.ready();

            if (getBasePackages() != null) {
                BeanRuleRegistry beanRuleRegistry = assistant.getBeanRuleRegistry();
                beanRuleRegistry.scanConfigurableBeans(getBasePackages());
            }

            if (contextRules != null || aspectranParameters != null) {
                ActivityContextParser parser = new HybridActivityContextParser(assistant);
                parser.setEncoding(getEncoding());
                parser.setUseXmlToApon(isUseAponToLoadXml());
                parser.setDebugMode(isDebugMode());
                if (contextRules != null) {
                    parser.parse(contextRules);
                } else {
                    parser.parse(aspectranParameters);
                }
                assistant = parser.getContextRuleAssistant();
                assistant.clearCurrentRuleAppender();
            }

            activityContext = createActivityContext(assistant);
            assistant.release();

            if (coreService != null) {
                coreService.setActivityContext(activityContext);
                activityContext.setRootService(coreService);
            }

            ((Component)activityContext).initialize();

            long elapsedTime = System.currentTimeMillis() - startTime;

            logger.info("ActivityContext build completed in " + elapsedTime + " ms");

            if (coreService == null) {
                // If it is driven by a builder without a service
                registerDestroyTask();
            } else {
                // Timer starts only if it is driven by a service
                startContextReloader();
            }

            this.active.set(true);

            return activityContext;
        } catch (Exception e) {
            throw new ActivityContextBuilderException("Failed to build ActivityContext", e);
        }
    }

    @Override
    public void destroy() {
        synchronized (this.buildDestroyMonitor) {
            doDestroy();
            removeDestroyTask();
        }
    }

    private void doDestroy() {
        if (this.active.get()) {
            stopContextReloader();
            if (activityContext != null) {
                ((Component)activityContext).destroy();
                activityContext = null;
            }
            if (coreService != null) {
                coreService.setActivityContext(null);
            }
            this.active.set(false);
        }
    }

    /**
     * Registers a shutdown hook with the JVM runtime, closing this context
     * on JVM shutdown unless it has already been closed at that time.
     */
    private void registerDestroyTask() {
        if (this.shutdownTask == null) {
            // Register a task to destroy the activity context on shutdown
            this.shutdownTask = ShutdownHook.addTask(() -> {
                synchronized (this.buildDestroyMonitor) {
                    doDestroy();
                    removeDestroyTask();
                }
            });
        }
    }

    /**
     * De-registers a shutdown hook with the JVM runtime.
     */
    private void removeDestroyTask() {
        // If we registered a JVM shutdown hook, we don't need it anymore now:
        // We've already explicitly closed the context.
        if (this.shutdownTask != null) {
            ShutdownHook.removeTask(this.shutdownTask);
            this.shutdownTask = null;
        }
    }

    @Override
    public boolean isActive() {
        return this.active.get();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy