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

org.nuiton.jaxx.runtime.application.ApplicationBootInitializerSupport Maven / Gradle / Ivy

The newest version!
package org.nuiton.jaxx.runtime.application;

/*-
 * #%L
 * JAXX :: Runtime
 * %%
 * Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import io.ultreia.java4all.i18n.I18n;
import io.ultreia.java4all.i18n.runtime.I18nConfiguration;
import io.ultreia.java4all.i18n.runtime.I18nLanguageProvider;
import io.ultreia.java4all.i18n.runtime.boot.DefaultI18nBootLoader;
import io.ultreia.java4all.i18n.runtime.boot.UserI18nBootLoader;
import io.ultreia.java4all.lang.Strings;
import io.ultreia.java4all.util.Zips;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Configurator;
import org.nuiton.jaxx.runtime.application.action.ActionExecutor;
import org.nuiton.jaxx.runtime.application.action.event.WizardActionWorkerExecutorListener;
import org.nuiton.jaxx.runtime.resources.UIResourcesProviders;
import org.nuiton.jaxx.runtime.swing.SwingUtil;

import java.awt.GraphicsEnvironment;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;

/**
 * Created by tchemit on 31/01/2018.
 *
 * @author Tony Chemit - [email protected]
 */
public abstract class ApplicationBootInitializerSupport> implements ApplicationBootInitializer {

    private static final String I18N_ARCHIVE = "/i18n.zip";
    private final String[] args;
    private final ImmutableList modules;
    private final ApplicationResourceManager resourceManager;
    private String LOG_CONFIGURATION_FILE = "/${application.id}-log4j.properties";
    private Logger log = LogManager.getLogger(ApplicationBootInitializerSupport.class);

    protected ApplicationBootInitializerSupport(String... args) {
        log.info(String.format("%s Create boot at %s with arguments: %s (%s)", ApplicationBoot.BOOT_LOG_PREFIX, new Date(), Arrays.toString(args), this));
        this.args = args;
        this.modules = ModuleInitializer.loadInitializer();
        this.resourceManager = new ApplicationResourceManager();
    }

    @Override
    public final String[] getArgs() {
        return args;
    }

    @Override
    public boolean haltOnExit() {
        return true;
    }

    @Override
    public final ActionExecutor createExecutor(ApplicationBoot boot, Config configuration, Context context) {
        log.info(String.format("%s Create executor (boot %s, configuration: %s, context: %s)", ApplicationBoot.BOOT_LOG_PREFIX, boot, configuration, context));
        ActionExecutor executor = new ActionExecutor(boot, context);
        executor.addActionExecutorListener(new WizardActionWorkerExecutorListener());
        return executor;
    }

    @Override
    public final void start(Config config, Context context) {
        log.info(String.format("%s Start application (version: %s) at %s (arguments: %s)", ApplicationBoot.BOOT_LOG_PREFIX, config.getApplicationVersion(), new Date(), Arrays.toString(args)));
        try {
            config.get().doAction(0);
        } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
            throw new RuntimeException("Can't execute command line actions", e);
        }
    }

    @Override
    public final void initOnce() throws ApplicationBootInitializerException {
        modules.forEach(ModuleInitializer::init);
    }

    @Override
    public final void close() {
        modules.forEach(ModuleInitializer::close);
    }

    @Override
    public final void init(Config config, Context context) throws ApplicationBootInitializerException {

        log.info(String.format("%s init application at %s (arguments: %s).", ApplicationBoot.BOOT_LOG_PREFIX, new Date(), Arrays.toString(getArgs())));

        long t0 = System.nanoTime();

        try { // 1 - init configuration
            config.initConfig(new Properties()/*getResourceManager().getResource(CaliResourceManager.DefaultBootInitializerResources.application)*/, getArgs());
            StringBuilder configBuilder = new StringBuilder(String.format("%s Configuration initialized with values:", ApplicationBoot.BOOT_LOG_PREFIX));
            config.printConfigurationOptions(configBuilder);
            log.info(configBuilder.toString());
        } catch (Exception e) {
            throw new ApplicationBootInitializerException("Can't load config application values", e);
        }

        registerResources(config);


        try {// 2 - init user directories
            initUserDirectories(config);
            log.info(String.format("%s User directories (%s) initialized.", ApplicationBoot.BOOT_LOG_PREFIX, config.getDataDirectory()));
        } catch (Exception e) {
            throw new ApplicationBootInitializerException("Can't init user directories", e);
        }

        try {// 3 - init log
            initLog(config);
            log.info(String.format("%s Logger initialized (use configuration file: %s.", ApplicationBoot.BOOT_LOG_PREFIX, config.getLogConfigurationFile()));
        } catch (Exception e) {
            throw new ApplicationBootInitializerException("Can't init log", e);
        }

        try {// 4 - init i18n
            initI18n(config);
            log.info(String.format("%s I18n (locale %s) is initialized.", ApplicationBoot.BOOT_LOG_PREFIX, config.getApplicationLocale().getDisplayLanguage()));
        } catch (Exception e) {
            throw new ApplicationBootInitializerException("Can't init i18n", e);
        }

        try {// 5 - init ui configurations
            initUIConfiguration(config);
        } catch (Exception e) {
            throw new ApplicationBootInitializerException("Can't init ui configuration", e);
        }

        try {// 6 - extra init
            initExtra(config, context);
        } catch (Exception e) {
            throw new ApplicationBootInitializerException("Can't init extra", e);
        }
        try {// 7 - init components
            initComponents(config, context);
        } catch (Exception e) {
            throw new ApplicationBootInitializerException("Can't init components", e);
        }


        String time = Strings.convertTime(t0, System.nanoTime());

        log.info(String.format("%s Context was initialized in %s.", ApplicationBoot.BOOT_LOG_PREFIX, time));
    }

    protected void registerResources(Config config) {
        resourceManager.registerResource(new ApplicationResourceManager.ClassPathResource(I18N_ARCHIVE));
        resourceManager.registerResource(new ApplicationResourceManager.ClassPathResource(LOG_CONFIGURATION_FILE = config.get().replaceRecursiveOptions(LOG_CONFIGURATION_FILE)));
    }

    public void initExtra(Config config, Context context) {

    }

    protected final void initComponents(Config configuration, Context context) {
        for (ApplicationContextComponent component : context.components()) {
            component.set(context, configuration);
        }
    }

    protected ApplicationResourceManager getResourceManager() {
        return resourceManager;
    }

    protected void initI18n(Config config) {

        I18n.close();

        File i18nDirectory = config.getI18nDirectory();
        I18nConfiguration i18nConfiguration = I18nConfiguration.createDefaultConfiguration();
        UserI18nBootLoader i18nInitializer = new UserI18nBootLoader(i18nDirectory.toPath(), new DefaultI18nBootLoader(i18nConfiguration)) {

            @Override
            protected void createUserI18nLayout(Path directory, I18nLanguageProvider delegateLanguageProvider) throws Exception {
                if (config.getI18nDefinitionFile().exists()) {
                    return;
                }
                super.createUserI18nLayout(directory,delegateLanguageProvider);

                // add also a archive with all i18n stuff (says i18n bundle + templates)

                URL resource = resourceManager.getResourceUrl(I18N_ARCHIVE);
                File archive = new File(directory.getParent().toFile(), resourceManager.getResourceFilename(I18N_ARCHIVE));
                try {
                    getResourceManager().copyResource(resource, archive, String.format("%s Copy i18n archive", ApplicationBoot.BOOT_LOG_PREFIX));
                    Zips.uncompressFiltred(archive, directory.toFile().getParentFile());
                } finally {
                    if (Files.exists(archive.toPath())) {
                        try {
                            Files.delete(archive.toPath());
                        } catch (IOException e) {
                            log.error(String.format("Could not delete i18n archive %s", archive));
                        }
                    }
                }

            }
        };

        long t00 = System.nanoTime();

        Locale locale = config.getApplicationLocale();

        I18n.init(i18nInitializer, locale);

//        TextTemplates.useDirectoryPath(new File(i18nDirectory, "ftl"));

        log.debug("i18n language : " + locale);
        log.debug("i18n loading time : " + Strings.convertTime(t00, System.nanoTime()));
    }

    protected void initLog(Config config) throws IOException {
        File logFile = config.getLogConfigurationFile();
        Preconditions.checkState(logFile.exists(), "Log config file %s does not exist.", logFile);
        log.debug(String.format("%s Loading log configuration from %s", ApplicationBoot.BOOT_LOG_PREFIX, logFile));

        List configLines = Files.readAllLines(logFile.toPath(), StandardCharsets.UTF_8);

        List finalLogConfigurationProperties = ApplicationConfiguration.loadProperties(configLines, config.get());
        StringBuilder finalConfiguration = new StringBuilder();
        for (String finalLogConfigurationProperty : finalLogConfigurationProperties) {
            finalConfiguration.append(finalLogConfigurationProperty).append("\n");
        }
        try (ByteArrayInputStream inputStream = new ByteArrayInputStream(finalConfiguration.toString().getBytes(StandardCharsets.UTF_8))) {
            Configurator.initialize(null, new ConfigurationSource(inputStream));
        }

        log = LogManager.getLogger(getClass());
        log.debug(String.format("%s Final log configuration done with file %s", ApplicationBoot.BOOT_LOG_PREFIX, logFile));
    }

    protected void initUserDirectories(Config config) throws IOException {

        // 1 - user data directory
        File dataDirectory = getResourceManager().createDirectory(config.getDataDirectory());
        log.debug(String.format("user data directory : %s", dataDirectory));

        // 2 - tmp directory
        getResourceManager().createDirectory(config.getTmpDirectory());
        FileUtils.cleanDirectory(config.getTmpDirectory());

        // 3 - resources directory
        File resourcesDirectory = config.getResourcesDirectory();
        if (resourcesDirectory.exists() && !config.getApplicationBuildVersion().equals(config.getApplicationVersion())) {

            // always clear resource directory
            log.debug(String.format("clear user resource data directory: %s", resourcesDirectory));
            if (config.getI18nDirectory().exists()) {
                FileUtils.cleanDirectory(config.getI18nDirectory());
            }
            if (config.getLogConfigurationFile().exists()) {
                FileUtils.deleteQuietly(config.getLogConfigurationFile());
            }
        }

        getResourceManager().createDirectory(resourcesDirectory);
        log.debug(String.format("user resource data directory: %s", resourcesDirectory));

        // 4 - resources log configuration file
        initLogFileDirectory(config);

    }

    protected void initLogFileDirectory(Config config) throws IOException {
        File file = config.getLogConfigurationFile();
        if (!file.exists()) {
            String message = String.format("%s Copy default log configuration file: %s", ApplicationBoot.BOOT_LOG_PREFIX, file);
            getResourceManager().copyResource(LOG_CONFIGURATION_FILE, file, message);
        }
    }

    protected void initUIConfiguration(Config config) {

        if (GraphicsEnvironment.isHeadless()) {
            return;
        }

        // prepare ui look&feel and load ui properties
        try {
            SwingUtil.initNimbusLoookAndFeel();
        } catch (Exception e) {
            // could not find nimbus look-and-feel
            log.warn("Could not use Look and Fell Nimbus, need at least version 1.6u10 of java.");
        } catch (Throwable e) {
            log.warn("No gui environment found");
        }
        UIResourcesProviders.load();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy